/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sts=4 et sw=4 tw=99: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. *//* * JavaScript bytecode interpreter. */#include"vm/Interpreter-inl.h"#include"mozilla/ArrayUtils.h"#include"mozilla/DebugOnly.h"#include"mozilla/FloatingPoint.h"#include"mozilla/Maybe.h"#include"mozilla/PodOperations.h"#include"mozilla/Sprintf.h"#include<string.h>#include"jsarray.h"#include"jsatom.h"#include"jscntxt.h"#include"jsfun.h"#include"jsgc.h"#include"jsiter.h"#include"jslibmath.h"#include"jsnum.h"#include"jsobj.h"#include"jsopcode.h"#include"jsprf.h"#include"jsscript.h"#include"jsstr.h"#include"builtin/Eval.h"#include"jit/AtomicOperations.h"#include"jit/BaselineJIT.h"#include"jit/Ion.h"#include"jit/IonAnalysis.h"#include"vm/AsyncFunction.h"#include"vm/AsyncIteration.h"#include"vm/Debugger.h"#include"vm/GeneratorObject.h"#include"vm/Opcodes.h"#include"vm/Scope.h"#include"vm/Shape.h"#include"vm/Stopwatch.h"#include"vm/TraceLogging.h"#include"jsatominlines.h"#include"jsboolinlines.h"#include"jsfuninlines.h"#include"jsscriptinlines.h"#include"jit/JitFrames-inl.h"#include"vm/Debugger-inl.h"#include"vm/EnvironmentObject-inl.h"#include"vm/NativeObject-inl.h"#include"vm/Probes-inl.h"#include"vm/Stack-inl.h"usingnamespacejs;usingnamespacejs::gc;usingmozilla::ArrayLength;usingmozilla::DebugOnly;usingmozilla::NumberEqualsInt32;usingmozilla::PodCopy;usingJS::ForOfIterator;template<boolEq>staticMOZ_ALWAYS_INLINEboolLooseEqualityOp(JSContext*cx,InterpreterRegs®s){HandleValuerval=regs.stackHandleAt(-1);HandleValuelval=regs.stackHandleAt(-2);boolcond;if(!LooselyEqual(cx,lval,rval,&cond))returnfalse;cond=(cond==Eq);regs.sp--;regs.sp[-1].setBoolean(cond);returntrue;}booljs::BoxNonStrictThis(JSContext*cx,HandleValuethisv,MutableHandleValuevp){/* * Check for SynthesizeFrame poisoning and fast constructors which * didn't check their callee properly. */MOZ_ASSERT(!thisv.isMagic());if(thisv.isNullOrUndefined()){vp.set(GetThisValue(cx->global()));returntrue;}if(thisv.isObject()){vp.set(thisv);returntrue;}JSObject*obj=PrimitiveToObject(cx,thisv);if(!obj)returnfalse;vp.setObject(*obj);returntrue;}booljs::GetFunctionThis(JSContext*cx,AbstractFramePtrframe,MutableHandleValueres){MOZ_ASSERT(frame.isFunctionFrame());MOZ_ASSERT(!frame.callee()->isArrow());if(frame.thisArgument().isObject()||frame.callee()->strict()||frame.callee()->isSelfHostedBuiltin()){res.set(frame.thisArgument());returntrue;}RootedValuethisv(cx,frame.thisArgument());returnBoxNonStrictThis(cx,thisv,res);}booljs::GetNonSyntacticGlobalThis(JSContext*cx,HandleObjectenvChain,MutableHandleValueres){RootedObjectenv(cx,envChain);while(true){if(IsExtensibleLexicalEnvironment(env)){res.set(env->as<LexicalEnvironmentObject>().thisValue());returntrue;}if(!env->enclosingEnvironment()){// This can only happen in Debugger eval frames: in that case we// don't always have a global lexical env, see EvaluateInEnv.MOZ_ASSERT(env->is<GlobalObject>());res.set(GetThisValue(env));returntrue;}env=env->enclosingEnvironment();}returntrue;}booljs::Debug_CheckSelfHosted(JSContext*cx,HandleValuefun){#ifndef DEBUGMOZ_CRASH("self-hosted checks should only be done in Debug builds");#endifRootedObjectfunObj(cx,UncheckedUnwrap(&fun.toObject()));MOZ_ASSERT(funObj->as<JSFunction>().isSelfHostedOrIntrinsic());// This is purely to police self-hosted code. There is no actual operation.returntrue;}staticinlineboolGetPropertyOperation(JSContext*cx,InterpreterFrame*fp,HandleScriptscript,jsbytecode*pc,MutableHandleValuelval,MutableHandleValuevp){JSOpop=JSOp(*pc);if(op==JSOP_LENGTH){if(IsOptimizedArguments(fp,lval)){vp.setInt32(fp->numActualArgs());returntrue;}if(GetLengthProperty(lval,vp))returntrue;}RootedPropertyNamename(cx,script->getName(pc));if(name==cx->names().callee&&IsOptimizedArguments(fp,lval)){vp.setObject(fp->callee());returntrue;}// Copy lval, because it might alias vp.RootedValuev(cx,lval);returnGetProperty(cx,v,name,vp);}staticinlineboolGetNameOperation(JSContext*cx,InterpreterFrame*fp,jsbytecode*pc,MutableHandleValuevp){RootedObjectenvChain(cx,fp->environmentChain());RootedPropertyNamename(cx,fp->script()->getName(pc));/* * Skip along the env chain to the enclosing global object. This is * used for GNAME opcodes where the bytecode emitter has determined a * name access must be on the global. It also insulates us from bugs * in the emitter: type inference will assume that GNAME opcodes are * accessing the global object, and the inferred behavior should match * the actual behavior even if the id could be found on the env chain * before the global object. */if(IsGlobalOp(JSOp(*pc))&&!fp->script()->hasNonSyntacticScope())envChain=&envChain->global().lexicalEnvironment();/* Kludge to allow (typeof foo == "undefined") tests. */JSOpop2=JSOp(pc[JSOP_GETNAME_LENGTH]);if(op2==JSOP_TYPEOF)returnGetEnvironmentName<GetNameMode::TypeOf>(cx,envChain,name,vp);returnGetEnvironmentName<GetNameMode::Normal>(cx,envChain,name,vp);}staticinlineboolGetImportOperation(JSContext*cx,InterpreterFrame*fp,jsbytecode*pc,MutableHandleValuevp){RootedObjectobj(cx,fp->environmentChain()),env(cx),pobj(cx);RootedPropertyNamename(cx,fp->script()->getName(pc));Rooted<PropertyResult>prop(cx);MOZ_ALWAYS_TRUE(LookupName(cx,name,obj,&env,&pobj,&prop));MOZ_ASSERT(env&&env->is<ModuleEnvironmentObject>());MOZ_ASSERT(env->as<ModuleEnvironmentObject>().hasImportBinding(name));returnFetchName<GetNameMode::Normal>(cx,env,pobj,name,prop,vp);}staticboolSetPropertyOperation(JSContext*cx,JSOpop,HandleValuelval,HandleIdid,HandleValuerval){MOZ_ASSERT(op==JSOP_SETPROP||op==JSOP_STRICTSETPROP);RootedObjectobj(cx,ToObjectFromStack(cx,lval));if(!obj)returnfalse;ObjectOpResultresult;returnSetProperty(cx,obj,id,rval,lval,result)&&result.checkStrictErrorOrWarning(cx,obj,id,op==JSOP_STRICTSETPROP);}JSFunction*js::MakeDefaultConstructor(JSContext*cx,HandleScriptscript,jsbytecode*pc,HandleObjectproto){JSOpop=JSOp(*pc);JSAtom*atom=script->getAtom(pc);boolderived=op==JSOP_DERIVEDCONSTRUCTOR;MOZ_ASSERT(derived==!!proto);jssrcnote*classNote=GetSrcNote(cx,script,pc);MOZ_ASSERT(classNote&&SN_TYPE(classNote)==SRC_CLASS_SPAN);PropertyName*lookup=derived?cx->names().DefaultDerivedClassConstructor:cx->names().DefaultBaseClassConstructor;RootedPropertyNameselfHostedName(cx,lookup);RootedAtomname(cx,atom==cx->names().empty?nullptr:atom);RootedFunctionctor(cx);if(!cx->runtime()->createLazySelfHostedFunctionClone(cx,selfHostedName,name,/* nargs = */!!derived,proto,TenuredObject,&ctor)){returnnullptr;}ctor->setIsConstructor();ctor->setIsClassConstructor();MOZ_ASSERT(ctor->infallibleIsDefaultClassConstructor(cx));// Create the script now, as the source span needs to be overridden for// toString. Calling toString on a class constructor must not return the// source for just the constructor function.JSScript*ctorScript=JSFunction::getOrCreateScript(cx,ctor);if(!ctorScript)returnnullptr;uint32_tclassStartOffset=GetSrcNoteOffset(classNote,0);uint32_tclassEndOffset=GetSrcNoteOffset(classNote,1);ctorScript->setDefaultClassConstructorSpan(script->sourceObject(),classStartOffset,classEndOffset);returnctor;}booljs::ReportIsNotFunction(JSContext*cx,HandleValuev,intnumToSkip,MaybeConstructconstruct){unsignederror=construct?JSMSG_NOT_CONSTRUCTOR:JSMSG_NOT_FUNCTION;intspIndex=numToSkip>=0?-(numToSkip+1):JSDVG_SEARCH_STACK;ReportValueError(cx,error,spIndex,v,nullptr);returnfalse;}JSObject*js::ValueToCallable(JSContext*cx,HandleValuev,intnumToSkip,MaybeConstructconstruct){if(v.isObject()&&v.toObject().isCallable()){return&v.toObject();}ReportIsNotFunction(cx,v,numToSkip,construct);returnnullptr;}boolRunState::maybeCreateThisForConstructor(JSContext*cx){if(isInvoke()){InvokeState&invoke=*asInvoke();if(invoke.constructing()&&invoke.args().thisv().isPrimitive()){RootedObjectcallee(cx,&invoke.args().callee());if(callee->isBoundFunction()){invoke.args().setThis(MagicValue(JS_UNINITIALIZED_LEXICAL));}elseif(script()->isDerivedClassConstructor()){MOZ_ASSERT(callee->as<JSFunction>().isClassConstructor());invoke.args().setThis(MagicValue(JS_UNINITIALIZED_LEXICAL));}else{MOZ_ASSERT(invoke.args().thisv().isMagic(JS_IS_CONSTRUCTING));RootedObjectnewTarget(cx,&invoke.args().newTarget().toObject());NewObjectKindnewKind=invoke.createSingleton()?SingletonObject:GenericObject;JSObject*obj=CreateThisForFunction(cx,callee,newTarget,newKind);if(!obj)returnfalse;invoke.args().setThis(ObjectValue(*obj));}}}returntrue;}staticMOZ_NEVER_INLINEboolInterpret(JSContext*cx,RunState&state);InterpreterFrame*InvokeState::pushInterpreterFrame(JSContext*cx){returncx->interpreterStack().pushInvokeFrame(cx,args_,construct_);}InterpreterFrame*ExecuteState::pushInterpreterFrame(JSContext*cx){returncx->interpreterStack().pushExecuteFrame(cx,script_,newTargetValue_,envChain_,evalInFrame_);}// MSVC with PGO inlines a lot of functions in RunScript, resulting in large// stack frames and stack overflow issues, see bug 1167883. Turn off PGO to// avoid this.#ifdef _MSC_VER# pragma optimize("g", off)#endifbooljs::RunScript(JSContext*cx,RunState&state){if(!CheckRecursionLimit(cx))returnfalse;// Since any script can conceivably GC, make sure it's safe to do so.cx->verifyIsSafeToGC();MOZ_DIAGNOSTIC_ASSERT(cx->compartment()->isSystem()||cx->runtime()->allowContentJS());MOZ_ASSERT(!cx->enableAccessValidation||cx->compartment()->isAccessValid());if(!Debugger::checkNoExecute(cx,state.script()))returnfalse;#if defined(MOZ_HAVE_RDTSC)js::AutoStopwatchstopwatch(cx);#endif // defined(MOZ_HAVE_RDTSC)GeckoProfilerEntryMarkermarker(cx->runtime(),state.script());state.script()->ensureNonLazyCanonicalFunction();if(jit::IsIonEnabled(cx)){jit::MethodStatusstatus=jit::CanEnter(cx,state);if(status==jit::Method_Error)returnfalse;if(status==jit::Method_Compiled){jit::JitExecStatusstatus=jit::IonCannon(cx,state);return!IsErrorStatus(status);}}if(jit::IsBaselineEnabled(cx)){jit::MethodStatusstatus=jit::CanEnterBaselineMethod(cx,state);if(status==jit::Method_Error)returnfalse;if(status==jit::Method_Compiled){jit::JitExecStatusstatus=jit::EnterBaselineMethod(cx,state);return!IsErrorStatus(status);}}if(state.isInvoke()){InvokeState&invoke=*state.asInvoke();TypeMonitorCall(cx,invoke.args(),invoke.constructing());}returnInterpret(cx,state);}#ifdef _MSC_VER# pragma optimize("", on)#endifstructAutoGCIfRequested{JSRuntime*runtime;explicitAutoGCIfRequested(JSRuntime*rt):runtime(rt){}~AutoGCIfRequested(){runtime->gc.gcIfRequested();}};/* * Find a function reference and its 'this' value implicit first parameter * under argc arguments on cx's stack, and call the function. Push missing * required arguments, allocate declared local variables, and pop everything * when done. Then push the return value. * * Note: This function DOES NOT call GetThisValue to munge |args.thisv()| if * necessary. The caller (usually the interpreter) must have performed * this step already! */booljs::InternalCallOrConstruct(JSContext*cx,constCallArgs&args,MaybeConstructconstruct){MOZ_ASSERT(args.length()<=ARGS_LENGTH_MAX);MOZ_ASSERT(!cx->zone()->types.activeAnalysis);/* Perform GC if necessary on exit from the function. */AutoGCIfRequestedgcIfRequested(cx->runtime());unsignedskipForCallee=args.length()+1+(construct==CONSTRUCT);if(args.calleev().isPrimitive())returnReportIsNotFunction(cx,args.calleev(),skipForCallee,construct);/* Invoke non-functions. */if(MOZ_UNLIKELY(!args.callee().is<JSFunction>())){MOZ_ASSERT_IF(construct,!args.callee().constructHook());JSNativecall=args.callee().callHook();if(!call)returnReportIsNotFunction(cx,args.calleev(),skipForCallee,construct);returnCallJSNative(cx,call,args);}/* Invoke native functions. */RootedFunctionfun(cx,&args.callee().as<JSFunction>());if(construct!=CONSTRUCT&&fun->isClassConstructor()){JS_ReportErrorNumberASCII(cx,GetErrorMessage,nullptr,JSMSG_CANT_CALL_CLASS_CONSTRUCTOR);returnfalse;}if(fun->isNative()){MOZ_ASSERT_IF(construct,!fun->isConstructor());JSNativenative=fun->native();if(!construct&&args.ignoresReturnValue()){constJSJitInfo*jitInfo=fun->jitInfo();if(jitInfo&&jitInfo->type()==JSJitInfo::IgnoresReturnValueNative)native=jitInfo->ignoresReturnValueMethod;}returnCallJSNative(cx,native,args);}if(!JSFunction::getOrCreateScript(cx,fun))returnfalse;/* Run function until JSOP_RETRVAL, JSOP_RETURN or error. */InvokeStatestate(cx,args,construct);// Check to see if createSingleton flag should be set for this frame.if(construct){jsbytecode*pc;if(JSScript*script=cx->currentScript(&pc)){if(ObjectGroup::useSingletonForNewObject(cx,script,pc))state.setCreateSingleton();}}boolok=RunScript(cx,state);MOZ_ASSERT_IF(ok&&construct,args.rval().isObject());returnok;}staticboolInternalCall(JSContext*cx,constAnyInvokeArgs&args){MOZ_ASSERT(args.array()+args.length()==args.end(),"must pass calling arguments to a calling attempt");if(args.thisv().isObject()){// We must call the thisValue hook in case we are not called from the// interpreter, where a prior bytecode has computed an appropriate// |this| already. But don't do that if fval is a DOM function.HandleValuefval=args.calleev();if(!fval.isObject()||!fval.toObject().is<JSFunction>()||!fval.toObject().as<JSFunction>().isNative()||!fval.toObject().as<JSFunction>().jitInfo()||fval.toObject().as<JSFunction>().jitInfo()->needsOuterizedThisObject()){JSObject*thisObj=&args.thisv().toObject();args.mutableThisv().set(GetThisValue(thisObj));}}returnInternalCallOrConstruct(cx,args,NO_CONSTRUCT);}booljs::CallFromStack(JSContext*cx,constCallArgs&args){returnInternalCall(cx,static_cast<constAnyInvokeArgs&>(args));}// ES7 rev 0c1bd3004329336774cbc90de727cd0cf5f11e93 7.3.12 Call.booljs::Call(JSContext*cx,HandleValuefval,HandleValuethisv,constAnyInvokeArgs&args,MutableHandleValuerval){// Explicitly qualify these methods to bypass AnyInvokeArgs's deliberate// shadowing.args.CallArgs::setCallee(fval);args.CallArgs::setThis(thisv);if(!InternalCall(cx,args))returnfalse;rval.set(args.rval());returntrue;}staticboolInternalConstruct(JSContext*cx,constAnyConstructArgs&args){MOZ_ASSERT(args.array()+args.length()+1==args.end(),"must pass constructing arguments to a construction attempt");MOZ_ASSERT(!JSFunction::class_.getConstruct());// Callers are responsible for enforcing these preconditions.MOZ_ASSERT(IsConstructor(args.calleev()),"trying to construct a value that isn't a constructor");MOZ_ASSERT(IsConstructor(args.CallArgs::newTarget()),"provided new.target value must be a constructor");MOZ_ASSERT(args.thisv().isMagic(JS_IS_CONSTRUCTING)||args.thisv().isObject());JSObject&callee=args.callee();if(callee.is<JSFunction>()){RootedFunctionfun(cx,&callee.as<JSFunction>());if(fun->isNative())returnCallJSNativeConstructor(cx,fun->native(),args);if(!InternalCallOrConstruct(cx,args,CONSTRUCT))returnfalse;MOZ_ASSERT(args.CallArgs::rval().isObject());returntrue;}JSNativeconstruct=callee.constructHook();MOZ_ASSERT(construct!=nullptr,"IsConstructor without a construct hook?");returnCallJSNativeConstructor(cx,construct,args);}// Check that |callee|, the callee in a |new| expression, is a constructor.staticboolStackCheckIsConstructorCalleeNewTarget(JSContext*cx,HandleValuecallee,HandleValuenewTarget){// Calls from the stack could have any old non-constructor callee.if(!IsConstructor(callee)){ReportValueError(cx,JSMSG_NOT_CONSTRUCTOR,JSDVG_SEARCH_STACK,callee,nullptr);returnfalse;}// The new.target has already been vetted by previous calls, or is the callee.// We can just assert that it's a constructor.MOZ_ASSERT(IsConstructor(newTarget));returntrue;}booljs::ConstructFromStack(JSContext*cx,constCallArgs&args){if(!StackCheckIsConstructorCalleeNewTarget(cx,args.calleev(),args.newTarget()))returnfalse;returnInternalConstruct(cx,static_cast<constAnyConstructArgs&>(args));}booljs::Construct(JSContext*cx,HandleValuefval,constAnyConstructArgs&args,HandleValuenewTarget,MutableHandleObjectobjp){MOZ_ASSERT(args.thisv().isMagic(JS_IS_CONSTRUCTING));// Explicitly qualify to bypass AnyConstructArgs's deliberate shadowing.args.CallArgs::setCallee(fval);args.CallArgs::newTarget().set(newTarget);if(!InternalConstruct(cx,args))returnfalse;MOZ_ASSERT(args.CallArgs::rval().isObject());objp.set(&args.CallArgs::rval().toObject());returntrue;}booljs::InternalConstructWithProvidedThis(JSContext*cx,HandleValuefval,HandleValuethisv,constAnyConstructArgs&args,HandleValuenewTarget,MutableHandleValuerval){args.CallArgs::setCallee(fval);MOZ_ASSERT(thisv.isObject());args.CallArgs::setThis(thisv);args.CallArgs::newTarget().set(newTarget);if(!InternalConstruct(cx,args))returnfalse;rval.set(args.CallArgs::rval());returntrue;}booljs::CallGetter(JSContext*cx,HandleValuethisv,HandleValuegetter,MutableHandleValuerval){// Invoke could result in another try to get or set the same id again, see// bug 355497.if(!CheckRecursionLimit(cx))returnfalse;FixedInvokeArgs<0>args(cx);returnCall(cx,getter,thisv,args,rval);}booljs::CallSetter(JSContext*cx,HandleValuethisv,HandleValuesetter,HandleValuev){if(!CheckRecursionLimit(cx))returnfalse;FixedInvokeArgs<1>args(cx);args[0].set(v);RootedValueignored(cx);returnCall(cx,setter,thisv,args,&ignored);}booljs::ExecuteKernel(JSContext*cx,HandleScriptscript,JSObject&envChainArg,constValue&newTargetValue,AbstractFramePtrevalInFrame,Value*result){MOZ_ASSERT_IF(script->isGlobalCode(),IsGlobalLexicalEnvironment(&envChainArg)||!IsSyntacticEnvironment(&envChainArg));#ifdef DEBUGRootedObjectterminatingEnv(cx,&envChainArg);while(IsSyntacticEnvironment(terminatingEnv))terminatingEnv=terminatingEnv->enclosingEnvironment();MOZ_ASSERT(terminatingEnv->is<GlobalObject>()||script->hasNonSyntacticScope());#endifif(script->treatAsRunOnce()){if(script->hasRunOnce()){JS_ReportErrorASCII(cx,"Trying to execute a run-once script multiple times");returnfalse;}script->setHasRunOnce();}if(script->isEmpty()){if(result)result->setUndefined();returntrue;}probes::StartExecution(script);ExecuteStatestate(cx,script,newTargetValue,envChainArg,evalInFrame,result);boolok=RunScript(cx,state);probes::StopExecution(script);returnok;}booljs::Execute(JSContext*cx,HandleScriptscript,JSObject&envChainArg,Value*rval){/* The env chain is something we control, so we know it can't have any outer objects on it. */RootedObjectenvChain(cx,&envChainArg);MOZ_ASSERT(!IsWindowProxy(envChain));if(script->module()){MOZ_RELEASE_ASSERT(envChain==script->module()->environment(),"Module scripts can only be executed in the module's environment");}else{MOZ_RELEASE_ASSERT(IsGlobalLexicalEnvironment(envChain)||script->hasNonSyntacticScope(),"Only global scripts with non-syntactic envs can be executed with ""interesting envchains");}/* Ensure the env chain is all same-compartment and terminates in a global. */#ifdef DEBUGJSObject*s=envChain;do{assertSameCompartment(cx,s);MOZ_ASSERT_IF(!s->enclosingEnvironment(),s->is<GlobalObject>());}while((s=s->enclosingEnvironment()));#endifreturnExecuteKernel(cx,script,*envChain,NullValue(),NullFramePtr()/* evalInFrame */,rval);}/* * ES6 (4-25-16) 12.10.4 InstanceofOperator */externbooljs::InstanceOfOperator(JSContext*cx,HandleObjectobj,HandleValuev,bool*bp){/* Step 1. is handled by caller. *//* Step 2. */RootedValuehasInstance(cx);RootedIdid(cx,SYMBOL_TO_JSID(cx->wellKnownSymbols().hasInstance));if(!GetProperty(cx,obj,obj,id,&hasInstance))returnfalse;if(!hasInstance.isNullOrUndefined()){if(!IsCallable(hasInstance))returnReportIsNotFunction(cx,hasInstance);/* Step 3. */RootedValuerval(cx);if(!Call(cx,hasInstance,obj,v,&rval))returnfalse;*bp=ToBoolean(rval);returntrue;}/* Step 4. */if(!obj->isCallable()){RootedValueval(cx,ObjectValue(*obj));returnReportIsNotFunction(cx,val);}/* Step 5. */returnOrdinaryHasInstance(cx,obj,v,bp);}booljs::HasInstance(JSContext*cx,HandleObjectobj,HandleValuev,bool*bp){constClass*clasp=obj->getClass();RootedValuelocal(cx,v);if(JSHasInstanceOphasInstance=clasp->getHasInstance())returnhasInstance(cx,obj,&local,bp);returnjs::InstanceOfOperator(cx,obj,local,bp);}staticinlineboolEqualGivenSameType(JSContext*cx,HandleValuelval,HandleValuerval,bool*equal){MOZ_ASSERT(SameType(lval,rval));if(lval.isString())returnEqualStrings(cx,lval.toString(),rval.toString(),equal);if(lval.isDouble()){*equal=(lval.toDouble()==rval.toDouble());returntrue;}if(lval.isGCThing()){// objects or symbols*equal=(lval.toGCThing()==rval.toGCThing());returntrue;}*equal=lval.get().payloadAsRawUint32()==rval.get().payloadAsRawUint32();MOZ_ASSERT_IF(lval.isUndefined()||lval.isNull(),*equal);returntrue;}staticinlineboolLooselyEqualBooleanAndOther(JSContext*cx,HandleValuelval,HandleValuerval,bool*result){MOZ_ASSERT(!rval.isBoolean());RootedValuelvalue(cx,Int32Value(lval.toBoolean()?1:0));// The tail-call would end up in Step 3.if(rval.isNumber()){*result=(lvalue.toNumber()==rval.toNumber());returntrue;}// The tail-call would end up in Step 6.if(rval.isString()){doublenum;if(!StringToNumber(cx,rval.toString(),&num))returnfalse;*result=(lvalue.toNumber()==num);returntrue;}returnLooselyEqual(cx,lvalue,rval,result);}// ES6 draft rev32 7.2.12 Abstract Equality Comparisonbooljs::LooselyEqual(JSContext*cx,HandleValuelval,HandleValuerval,bool*result){// Step 3.if(SameType(lval,rval))returnEqualGivenSameType(cx,lval,rval,result);// Handle int32 x double.if(lval.isNumber()&&rval.isNumber()){*result=(lval.toNumber()==rval.toNumber());returntrue;}// Step 4. This a bit more complex, because of the undefined emulating object.if(lval.isNullOrUndefined()){// We can return early here, because null | undefined is only equal to the same set.*result=rval.isNullOrUndefined()||(rval.isObject()&&EmulatesUndefined(&rval.toObject()));returntrue;}// Step 5.if(rval.isNullOrUndefined()){MOZ_ASSERT(!lval.isNullOrUndefined());*result=lval.isObject()&&EmulatesUndefined(&lval.toObject());returntrue;}// Step 6.if(lval.isNumber()&&rval.isString()){doublenum;if(!StringToNumber(cx,rval.toString(),&num))returnfalse;*result=(lval.toNumber()==num);returntrue;}// Step 7.if(lval.isString()&&rval.isNumber()){doublenum;if(!StringToNumber(cx,lval.toString(),&num))returnfalse;*result=(num==rval.toNumber());returntrue;}// Step 8.if(lval.isBoolean())returnLooselyEqualBooleanAndOther(cx,lval,rval,result);// Step 9.if(rval.isBoolean())returnLooselyEqualBooleanAndOther(cx,rval,lval,result);// Step 10.if((lval.isString()||lval.isNumber()||lval.isSymbol())&&rval.isObject()){RootedValuervalue(cx,rval);if(!ToPrimitive(cx,&rvalue))returnfalse;returnLooselyEqual(cx,lval,rvalue,result);}// Step 11.if(lval.isObject()&&(rval.isString()||rval.isNumber()||rval.isSymbol())){RootedValuelvalue(cx,lval);if(!ToPrimitive(cx,&lvalue))returnfalse;returnLooselyEqual(cx,lvalue,rval,result);}// Step 12.*result=false;returntrue;}booljs::StrictlyEqual(JSContext*cx,HandleValuelval,HandleValuerval,bool*equal){if(SameType(lval,rval))returnEqualGivenSameType(cx,lval,rval,equal);if(lval.isNumber()&&rval.isNumber()){*equal=(lval.toNumber()==rval.toNumber());returntrue;}*equal=false;returntrue;}staticinlineboolIsNegativeZero(constValue&v){returnv.isDouble()&&mozilla::IsNegativeZero(v.toDouble());}staticinlineboolIsNaN(constValue&v){returnv.isDouble()&&mozilla::IsNaN(v.toDouble());}booljs::SameValue(JSContext*cx,HandleValuev1,HandleValuev2,bool*same){if(IsNegativeZero(v1)){*same=IsNegativeZero(v2);returntrue;}if(IsNegativeZero(v2)){*same=false;returntrue;}if(IsNaN(v1)&&IsNaN(v2)){*same=true;returntrue;}returnStrictlyEqual(cx,v1,v2,same);}JSTypejs::TypeOfObject(JSObject*obj){if(EmulatesUndefined(obj))returnJSTYPE_UNDEFINED;if(obj->isCallable())returnJSTYPE_FUNCTION;returnJSTYPE_OBJECT;}JSTypejs::TypeOfValue(constValue&v){if(v.isNumber())returnJSTYPE_NUMBER;if(v.isString())returnJSTYPE_STRING;if(v.isNull())returnJSTYPE_OBJECT;if(v.isUndefined())returnJSTYPE_UNDEFINED;if(v.isObject())returnTypeOfObject(&v.toObject());if(v.isBoolean())returnJSTYPE_BOOLEAN;MOZ_ASSERT(v.isSymbol());returnJSTYPE_SYMBOL;}booljs::CheckClassHeritageOperation(JSContext*cx,HandleValueheritage){if(IsConstructor(heritage))returntrue;if(heritage.isNull())returntrue;if(heritage.isObject()){ReportIsNotFunction(cx,heritage,0,CONSTRUCT);returnfalse;}ReportValueError2(cx,JSMSG_BAD_HERITAGE,-1,heritage,nullptr,"not an object or null");returnfalse;}JSObject*js::ObjectWithProtoOperation(JSContext*cx,HandleValueval){if(!val.isObjectOrNull()){ReportValueError(cx,JSMSG_NOT_OBJORNULL,-1,val,nullptr);returnnullptr;}RootedObjectproto(cx,val.toObjectOrNull());returnNewObjectWithGivenProto<PlainObject>(cx,proto);}JSObject*js::FunWithProtoOperation(JSContext*cx,HandleFunctionfun,HandleObjectparent,HandleObjectproto){returnCloneFunctionObjectIfNotSingleton(cx,fun,parent,proto);}/* * Enter the new with environment using an object at sp[-1] and associate the * depth of the with block with sp + stackIndex. */booljs::EnterWithOperation(JSContext*cx,AbstractFramePtrframe,HandleValueval,Handle<WithScope*>scope){RootedObjectobj(cx);if(val.isObject()){obj=&val.toObject();}else{obj=ToObject(cx,val);if(!obj)returnfalse;}RootedObjectenvChain(cx,frame.environmentChain());WithEnvironmentObject*withobj=WithEnvironmentObject::create(cx,obj,envChain,scope);if(!withobj)returnfalse;frame.pushOnEnvironmentChain(*withobj);returntrue;}staticvoidPopEnvironment(JSContext*cx,EnvironmentIter&ei){switch(ei.scope().kind()){caseScopeKind::Lexical:caseScopeKind::SimpleCatch:caseScopeKind::Catch:caseScopeKind::NamedLambda:caseScopeKind::StrictNamedLambda:if(MOZ_UNLIKELY(cx->compartment()->isDebuggee()))DebugEnvironments::onPopLexical(cx,ei);if(ei.scope().hasEnvironment())ei.initialFrame().popOffEnvironmentChain<LexicalEnvironmentObject>();break;caseScopeKind::With:if(MOZ_UNLIKELY(cx->compartment()->isDebuggee()))DebugEnvironments::onPopWith(ei.initialFrame());ei.initialFrame().popOffEnvironmentChain<WithEnvironmentObject>();break;caseScopeKind::Function:if(MOZ_UNLIKELY(cx->compartment()->isDebuggee()))DebugEnvironments::onPopCall(cx,ei.initialFrame());if(ei.scope().hasEnvironment())ei.initialFrame().popOffEnvironmentChain<CallObject>();break;caseScopeKind::FunctionBodyVar:caseScopeKind::ParameterExpressionVar:caseScopeKind::StrictEval:if(MOZ_UNLIKELY(cx->compartment()->isDebuggee()))DebugEnvironments::onPopVar(cx,ei);if(ei.scope().hasEnvironment())ei.initialFrame().popOffEnvironmentChain<VarEnvironmentObject>();break;caseScopeKind::Eval:caseScopeKind::Global:caseScopeKind::NonSyntactic:caseScopeKind::Module:break;caseScopeKind::WasmFunction:MOZ_CRASH("wasm is not interpreted");break;}}// Unwind environment chain and iterator to match the env corresponding to// the given bytecode position.voidjs::UnwindEnvironment(JSContext*cx,EnvironmentIter&ei,jsbytecode*pc){if(!ei.withinInitialFrame())return;RootedScopescope(cx,ei.initialFrame().script()->innermostScope(pc));#ifdef DEBUG// A frame's environment chain cannot be unwound to anything enclosing the// body scope of a script. This includes the parameter defaults// environment and the decl env object. These environments, once pushed// onto the environment chain, are expected to be there for the duration// of the frame.//// Attempting to unwind to the parameter defaults code in a script is a// bug; that section of code has no try-catch blocks.JSScript*script=ei.initialFrame().script();for(uint32_ti=0;i<script->bodyScopeIndex();i++)MOZ_ASSERT(scope!=script->getScope(i));#endiffor(;ei.maybeScope()!=scope;ei++)PopEnvironment(cx,ei);}// Unwind all environments. This is needed because block scopes may cover the// first bytecode at a script's main(). e.g.,//// function f() { { let i = 0; } }//// will have no pc location distinguishing the first block scope from the// outermost function scope.voidjs::UnwindAllEnvironmentsInFrame(JSContext*cx,EnvironmentIter&ei){for(;ei.withinInitialFrame();ei++)PopEnvironment(cx,ei);}// Compute the pc needed to unwind the environment to the beginning of a try// block. We cannot unwind to *after* the JSOP_TRY, because that might be the// first opcode of an inner scope, with the same problem as above. e.g.,//// try { { let x; } }//// will have no pc location distinguishing the try block scope from the inner// let block scope.jsbytecode*js::UnwindEnvironmentToTryPc(JSScript*script,JSTryNote*tn){jsbytecode*pc=script->main()+tn->start;if(tn->kind==JSTRY_CATCH||tn->kind==JSTRY_FINALLY){pc-=JSOP_TRY_LENGTH;MOZ_ASSERT(*pc==JSOP_TRY);}elseif(tn->kind==JSTRY_DESTRUCTURING_ITERCLOSE){pc-=JSOP_TRY_DESTRUCTURING_ITERCLOSE_LENGTH;MOZ_ASSERT(*pc==JSOP_TRY_DESTRUCTURING_ITERCLOSE);}returnpc;}staticboolForcedReturn(JSContext*cx,EnvironmentIter&ei,InterpreterRegs®s,boolframeOk=true){boolok=Debugger::onLeaveFrame(cx,regs.fp(),regs.pc,frameOk);// Point the frame to the end of the script, regardless of error. The// caller must jump to the correct continuation depending on 'ok'.regs.setToEndOfScript();returnok;}staticboolForcedReturn(JSContext*cx,InterpreterRegs®s){EnvironmentIterei(cx,regs.fp(),regs.pc);returnForcedReturn(cx,ei,regs);}staticvoidSettleOnTryNote(JSContext*cx,JSTryNote*tn,EnvironmentIter&ei,InterpreterRegs®s){// Unwind the environment to the beginning of the JSOP_TRY.UnwindEnvironment(cx,ei,UnwindEnvironmentToTryPc(regs.fp()->script(),tn));// Set pc to the first bytecode after the the try note to point// to the beginning of catch or finally.regs.pc=regs.fp()->script()->main()+tn->start+tn->length;regs.sp=regs.spForStackDepth(tn->stackDepth);}classInterpreterFrameStackDepthOp{constInterpreterRegs®s_;public:explicitInterpreterFrameStackDepthOp(constInterpreterRegs®s):regs_(regs){}uint32_toperator()(){returnregs_.stackDepth();}};classTryNoteIterInterpreter:publicTryNoteIter<InterpreterFrameStackDepthOp>{public:TryNoteIterInterpreter(JSContext*cx,constInterpreterRegs®s):TryNoteIter(cx,regs.fp()->script(),regs.pc,InterpreterFrameStackDepthOp(regs)){}};staticvoidUnwindIteratorsForUncatchableException(JSContext*cx,constInterpreterRegs®s){// c.f. the regular (catchable) TryNoteIterInterpreter loop in// ProcessTryNotes.for(TryNoteIterInterpretertni(cx,regs);!tni.done();++tni){JSTryNote*tn=*tni;if(tn->kind==JSTRY_FOR_IN){Value*sp=regs.spForStackDepth(tn->stackDepth);UnwindIteratorForUncatchableException(cx,&sp[-1].toObject());}}}enumHandleErrorContinuation{SuccessfulReturnContinuation,ErrorReturnContinuation,CatchContinuation,FinallyContinuation};staticHandleErrorContinuationProcessTryNotes(JSContext*cx,EnvironmentIter&ei,InterpreterRegs®s){boolinForOfIterClose=false;for(TryNoteIterInterpretertni(cx,regs);!tni.done();++tni){JSTryNote*tn=*tni;switch(tn->kind){caseJSTRY_CATCH:/* Catch cannot intercept the closing of a generator. */if(cx->isClosingGenerator())break;// If IteratorClose due to abnormal completion threw inside a// for-of loop, it is not catchable by try statements inside of// the for-of loop.//// This is handled by this weirdness in the exception handler// instead of in bytecode because it is hard to do so in bytecode://// 1. IteratorClose emitted due to abnormal completion (break,// throw, return) are emitted inline, at the source location of// the break, throw, or return statement. For example://// for (x of iter) {// try { return; } catch (e) { }// }//// From the try-note nesting's perspective, the IteratorClose// resulting from |return| is covered by the inner try, when it// should not be.//// 2. Try-catch notes cannot be disjoint. That is, we can't have// multiple notes with disjoint pc ranges jumping to the same// catch block.if(inForOfIterClose)break;SettleOnTryNote(cx,tn,ei,regs);returnCatchContinuation;caseJSTRY_FINALLY:// See note above.if(inForOfIterClose)break;SettleOnTryNote(cx,tn,ei,regs);returnFinallyContinuation;caseJSTRY_FOR_IN:{/* This is similar to JSOP_ENDITER in the interpreter loop. */DebugOnly<jsbytecode*>pc=regs.fp()->script()->main()+tn->start+tn->length;MOZ_ASSERT(JSOp(*pc)==JSOP_ENDITER);Value*sp=regs.spForStackDepth(tn->stackDepth);RootedObjectobj(cx,&sp[-1].toObject());if(!UnwindIteratorForException(cx,obj)){// We should only settle on the note only if// UnwindIteratorForException itself threw, as// onExceptionUnwind should be called anew with the new// location of the throw (the iterator). Indeed, we must// settle to avoid infinitely handling the same exception.SettleOnTryNote(cx,tn,ei,regs);returnErrorReturnContinuation;}break;}caseJSTRY_DESTRUCTURING_ITERCLOSE:{// Whether the destructuring iterator is done is at the top of the// stack. The iterator object is second from the top.MOZ_ASSERT(tn->stackDepth>1);Value*sp=regs.spForStackDepth(tn->stackDepth);RootedValuedoneValue(cx,sp[-1]);booldone=ToBoolean(doneValue);if(!done){RootedObjectiterObject(cx,&sp[-2].toObject());if(!IteratorCloseForException(cx,iterObject)){SettleOnTryNote(cx,tn,ei,regs);returnErrorReturnContinuation;}}break;}caseJSTRY_FOR_OF_ITERCLOSE:inForOfIterClose=true;break;caseJSTRY_FOR_OF:inForOfIterClose=false;break;caseJSTRY_LOOP:break;default:MOZ_CRASH("Invalid try note");}}returnSuccessfulReturnContinuation;}booljs::HandleClosingGeneratorReturn(JSContext*cx,AbstractFramePtrframe,boolok){/* * Propagate the exception or error to the caller unless the exception * is an asynchronous return from a generator. */if(cx->isClosingGenerator()){cx->clearPendingException();ok=true;SetReturnValueForClosingGenerator(cx,frame);}returnok;}staticHandleErrorContinuationHandleError(JSContext*cx,InterpreterRegs®s){MOZ_ASSERT(regs.fp()->script()->containsPC(regs.pc));if(regs.fp()->script()->hasScriptCounts()){PCCounts*counts=regs.fp()->script()->getThrowCounts(regs.pc);// If we failed to allocate, then skip the increment and continue to// handle the exception.if(counts)counts->numExec()++;}EnvironmentIterei(cx,regs.fp(),regs.pc);boolok=false;again:if(cx->isExceptionPending()){/* Call debugger throw hooks. */if(!cx->isClosingGenerator()){JSTrapStatusstatus=Debugger::onExceptionUnwind(cx,regs.fp());switch(status){caseJSTRAP_ERROR:gotoagain;caseJSTRAP_CONTINUE:caseJSTRAP_THROW:break;caseJSTRAP_RETURN:UnwindIteratorsForUncatchableException(cx,regs);if(!ForcedReturn(cx,ei,regs))returnErrorReturnContinuation;returnSuccessfulReturnContinuation;default:MOZ_CRASH("Bad Debugger::onExceptionUnwind status");}}HandleErrorContinuationres=ProcessTryNotes(cx,ei,regs);switch(res){caseSuccessfulReturnContinuation:break;caseErrorReturnContinuation:gotoagain;caseCatchContinuation:caseFinallyContinuation:// No need to increment the PCCounts number of execution here, as// the interpreter increments any PCCounts if present.MOZ_ASSERT_IF(regs.fp()->script()->hasScriptCounts(),regs.fp()->script()->maybeGetPCCounts(regs.pc));returnres;}ok=HandleClosingGeneratorReturn(cx,regs.fp(),ok);ok=Debugger::onLeaveFrame(cx,regs.fp(),regs.pc,ok);}else{// We may be propagating a forced return from the interrupt// callback, which cannot easily force a return.if(MOZ_UNLIKELY(cx->isPropagatingForcedReturn())){cx->clearPropagatingForcedReturn();if(!ForcedReturn(cx,ei,regs))returnErrorReturnContinuation;returnSuccessfulReturnContinuation;}UnwindIteratorsForUncatchableException(cx,regs);}// After this point, we will pop the frame regardless. Settle the frame on// the end of the script.regs.setToEndOfScript();returnok?SuccessfulReturnContinuation:ErrorReturnContinuation;}#define REGS (activation.regs())#define PUSH_COPY(v) do { *REGS.sp++ = (v); assertSameCompartmentDebugOnly(cx, REGS.sp[-1]); } while (0)#define PUSH_COPY_SKIP_CHECK(v) *REGS.sp++ = (v)#define PUSH_NULL() REGS.sp++->setNull()#define PUSH_UNDEFINED() REGS.sp++->setUndefined()#define PUSH_BOOLEAN(b) REGS.sp++->setBoolean(b)#define PUSH_DOUBLE(d) REGS.sp++->setDouble(d)#define PUSH_INT32(i) REGS.sp++->setInt32(i)#define PUSH_SYMBOL(s) REGS.sp++->setSymbol(s)#define PUSH_STRING(s) do { REGS.sp++->setString(s); assertSameCompartmentDebugOnly(cx, REGS.sp[-1]); } while (0)#define PUSH_OBJECT(obj) do { REGS.sp++->setObject(obj); assertSameCompartmentDebugOnly(cx, REGS.sp[-1]); } while (0)#define PUSH_OBJECT_OR_NULL(obj) do { REGS.sp++->setObjectOrNull(obj); assertSameCompartmentDebugOnly(cx, REGS.sp[-1]); } while (0)#define PUSH_MAGIC(magic) REGS.sp++->setMagic(magic)#define POP_COPY_TO(v) (v) = *--REGS.sp#define POP_RETURN_VALUE() REGS.fp()->setReturnValue(*--REGS.sp)#define FETCH_OBJECT(cx, n, obj) \ JS_BEGIN_MACRO \ HandleValue val = REGS.stackHandleAt(n); \ obj = ToObjectFromStack((cx), (val)); \ if (!obj) \ goto error; \ JS_END_MACRO/* * Same for JSOP_SETNAME and JSOP_SETPROP, which differ only slightly but * remain distinct for the decompiler. */JS_STATIC_ASSERT(JSOP_SETNAME_LENGTH==JSOP_SETPROP_LENGTH);/* See TRY_BRANCH_AFTER_COND. */JS_STATIC_ASSERT(JSOP_IFNE_LENGTH==JSOP_IFEQ_LENGTH);JS_STATIC_ASSERT(JSOP_IFNE==JSOP_IFEQ+1);/* * Compute the implicit |this| parameter for a call expression where the callee * funval was resolved from an unqualified name reference to a property on obj * (an object on the env chain). * * We can avoid computing |this| eagerly and push the implicit callee-coerced * |this| value, undefined, if either of these conditions hold: * * 1. The nominal |this|, obj, is a global object. * * 2. The nominal |this|, obj, has one of LexicalEnvironment or Call class (this * is what IsCacheableEnvironment tests). Such objects-as-envs must be * censored with undefined. * * Otherwise, we bind |this| to the result of GetThisValue(). Only names inside * |with| statements and embedding-specific environment objects fall into this * category. * * If the callee is a strict mode function, then code implementing JSOP_THIS * in the interpreter and JITs will leave undefined as |this|. If funval is a * function not in strict mode, JSOP_THIS code replaces undefined with funval's * global. */staticinlineValueComputeImplicitThis(JSObject*obj){if(obj->is<GlobalObject>())returnUndefinedValue();if(IsCacheableEnvironment(obj))returnUndefinedValue();returnGetThisValue(obj);}staticMOZ_ALWAYS_INLINEboolAddOperation(JSContext*cx,MutableHandleValuelhs,MutableHandleValuerhs,MutableHandleValueres){if(lhs.isInt32()&&rhs.isInt32()){int32_tl=lhs.toInt32(),r=rhs.toInt32();int32_tt;if(MOZ_LIKELY(SafeAdd(l,r,&t))){res.setInt32(t);returntrue;}}if(!ToPrimitive(cx,lhs))returnfalse;if(!ToPrimitive(cx,rhs))returnfalse;boollIsString,rIsString;if((lIsString=lhs.isString())|(rIsString=rhs.isString())){JSString*lstr;if(lIsString){lstr=lhs.toString();}else{lstr=ToString<CanGC>(cx,lhs);if(!lstr)returnfalse;}JSString*rstr;if(rIsString){rstr=rhs.toString();}else{// Save/restore lstr in case of GC activity under ToString.lhs.setString(lstr);rstr=ToString<CanGC>(cx,rhs);if(!rstr)returnfalse;lstr=lhs.toString();}JSString*str=ConcatStrings<NoGC>(cx,lstr,rstr);if(!str){RootedStringnlstr(cx,lstr),nrstr(cx,rstr);str=ConcatStrings<CanGC>(cx,nlstr,nrstr);if(!str)returnfalse;}res.setString(str);}else{doublel,r;if(!ToNumber(cx,lhs,&l)||!ToNumber(cx,rhs,&r))returnfalse;res.setNumber(l+r);}returntrue;}staticMOZ_ALWAYS_INLINEboolSubOperation(JSContext*cx,HandleValuelhs,HandleValuerhs,MutableHandleValueres){doubled1,d2;if(!ToNumber(cx,lhs,&d1)||!ToNumber(cx,rhs,&d2))returnfalse;res.setNumber(d1-d2);returntrue;}staticMOZ_ALWAYS_INLINEboolMulOperation(JSContext*cx,HandleValuelhs,HandleValuerhs,MutableHandleValueres){doubled1,d2;if(!ToNumber(cx,lhs,&d1)||!ToNumber(cx,rhs,&d2))returnfalse;res.setNumber(d1*d2);returntrue;}staticMOZ_ALWAYS_INLINEboolDivOperation(JSContext*cx,HandleValuelhs,HandleValuerhs,MutableHandleValueres){doubled1,d2;if(!ToNumber(cx,lhs,&d1)||!ToNumber(cx,rhs,&d2))returnfalse;res.setNumber(NumberDiv(d1,d2));returntrue;}staticMOZ_ALWAYS_INLINEboolModOperation(JSContext*cx,HandleValuelhs,HandleValuerhs,MutableHandleValueres){int32_tl,r;if(lhs.isInt32()&&rhs.isInt32()&&(l=lhs.toInt32())>=0&&(r=rhs.toInt32())>0){int32_tmod=l%r;res.setInt32(mod);returntrue;}doubled1,d2;if(!ToNumber(cx,lhs,&d1)||!ToNumber(cx,rhs,&d2))returnfalse;res.setNumber(NumberMod(d1,d2));returntrue;}staticMOZ_ALWAYS_INLINEboolSetObjectElementOperation(JSContext*cx,HandleObjectobj,HandleIdid,HandleValuevalue,HandleValuereceiver,boolstrict,JSScript*script=nullptr,jsbytecode*pc=nullptr){// receiver != obj happens only at super[expr], where we expect to find the property// People probably aren't building hashtables with |super| anyway.TypeScript::MonitorAssign(cx,obj,id);if(obj->isNative()&&JSID_IS_INT(id)){uint32_tlength=obj->as<NativeObject>().getDenseInitializedLength();int32_ti=JSID_TO_INT(id);if((uint32_t)i>=length){// Annotate script if provided with information (e.g. baseline)if(script&&script->hasBaselineScript()&&IsSetElemPC(pc))script->baselineScript()->noteHasDenseAdd(script->pcToOffset(pc));}}// Set the HadElementsAccess flag on the object if needed. This flag is// used to do more eager dictionary-mode conversion for objects that are// used as hashmaps. Set this flag only for objects with many properties,// to avoid unnecessary Shape changes.if(obj->isNative()&&JSID_IS_ATOM(id)&&!obj->as<NativeObject>().inDictionaryMode()&&!obj->hadElementsAccess()&&obj->as<NativeObject>().slotSpan()>PropertyTree::MAX_HEIGHT_WITH_ELEMENTS_ACCESS/3){if(!JSObject::setHadElementsAccess(cx,obj))returnfalse;}ObjectOpResultresult;returnSetProperty(cx,obj,id,value,receiver,result)&&result.checkStrictErrorOrWarning(cx,obj,id,strict);}/* * Get the innermost enclosing function that has a 'this' binding. * * Implements ES6 12.3.5.2 GetSuperConstructor() steps 1-3, including * the loop in ES6 8.3.2 GetThisEnvironment(). Our implementation of * ES6 12.3.5.3 MakeSuperPropertyReference() also uses this code. */staticJSFunction&GetSuperEnvFunction(JSContext*cx,InterpreterRegs®s){JSObject*env=regs.fp()->environmentChain();Scope*scope=regs.fp()->script()->innermostScope(regs.pc);for(EnvironmentIterei(cx,env,scope);ei;ei++){if(ei.hasSyntacticEnvironment()&&ei.scope().is<FunctionScope>()){JSFunction&callee=ei.environment().as<CallObject>().callee();// Arrow functions don't have the information we're looking for,// their enclosing scopes do. Nevertheless, they might have call// objects. Skip them to find what we came for.if(callee.isArrow())continue;returncallee;}}MOZ_CRASH("unexpected env chain for GetSuperEnvFunction");}/* * As an optimization, the interpreter creates a handful of reserved Rooted<T> * variables at the beginning, thus inserting them into the Rooted list once * upon entry. ReservedRooted "borrows" a reserved Rooted variable and uses it * within a local scope, resetting the value to nullptr (or the appropriate * equivalent for T) at scope end. This avoids inserting/removing the Rooted * from the rooter list, while preventing stale values from being kept alive * unnecessarily. */template<typenameT>classReservedRooted:publicRootedBase<T,ReservedRooted<T>>{Rooted<T>*savedRoot;public:ReservedRooted(Rooted<T>*root,constT&ptr):savedRoot(root){*root=ptr;}explicitReservedRooted(Rooted<T>*root):savedRoot(root){*root=JS::GCPolicy<T>::initial();}~ReservedRooted(){*savedRoot=JS::GCPolicy<T>::initial();}voidset(constT&p)const{*savedRoot=p;}operatorHandle<T>(){return*savedRoot;}operatorRooted<T>&(){return*savedRoot;}MutableHandle<T>operator&(){return&*savedRoot;}DECLARE_NONPOINTER_ACCESSOR_METHODS(savedRoot->get())DECLARE_NONPOINTER_MUTABLE_ACCESSOR_METHODS(savedRoot->get())DECLARE_POINTER_CONSTREF_OPS(T)DECLARE_POINTER_ASSIGN_OPS(ReservedRooted,T)};staticMOZ_NEVER_INLINEboolInterpret(JSContext*cx,RunState&state){/* * Define macros for an interpreter loop. Opcode dispatch may be either by a * switch statement or by indirect goto (aka a threaded interpreter), depending * on compiler support. * * Threaded interpretation appears to be well-supported by GCC 3 and higher. * IBM's C compiler when run with the right options (e.g., -qlanglvl=extended) * also supports threading. Ditto the SunPro C compiler. */#if (defined(__GNUC__) || \ (__IBMC__ >= 700 && defined __IBM_COMPUTED_GOTO) || \ __SUNPRO_C >= 0x570)// Non-standard but faster indirect-goto-based dispatch.# define INTERPRETER_LOOP()# define CASE(OP) label_##OP:# define DEFAULT() label_default:# define DISPATCH_TO(OP) goto* addresses[(OP)]# define LABEL(X) (&&label_##X)// Use addresses instead of offsets to optimize for runtime speed over// load-time relocation overhead.staticconstvoid*constaddresses[EnableInterruptsPseudoOpcode+1]={# define OPCODE_LABEL(op, ...) LABEL(op),FOR_EACH_OPCODE(OPCODE_LABEL)# undef OPCODE_LABEL# define TRAILING_LABEL(v) \ ((v) == EnableInterruptsPseudoOpcode \ ? LABEL(EnableInterruptsPseudoOpcode) \ : LABEL(default)),FOR_EACH_TRAILING_UNUSED_OPCODE(TRAILING_LABEL)# undef TRAILING_LABEL};#else// Portable switch-based dispatch.# define INTERPRETER_LOOP() the_switch: switch (switchOp)# define CASE(OP) case OP:# define DEFAULT() default:# define DISPATCH_TO(OP) \ JS_BEGIN_MACRO \ switchOp = (OP); \ goto the_switch; \ JS_END_MACRO// This variable is effectively a parameter to the_switch.jsbytecodeswitchOp;#endif/* * Increment REGS.pc by N, load the opcode at that position, * and jump to the code to execute it. * * When Debugger puts a script in single-step mode, all js::Interpret * invocations that might be presently running that script must have * interrupts enabled. It's not practical to simply check * script->stepModeEnabled() at each point some callee could have changed * it, because there are so many places js::Interpret could possibly cause * JavaScript to run: each place an object might be coerced to a primitive * or a number, for example. So instead, we expose a simple mechanism to * let Debugger tweak the affected js::Interpret frames when an onStep * handler is added: calling activation.enableInterruptsUnconditionally() * will enable interrupts, and activation.opMask() is or'd with the opcode * to implement a simple alternate dispatch. */#define ADVANCE_AND_DISPATCH(N) \ JS_BEGIN_MACRO \ REGS.pc += (N); \ SANITY_CHECKS(); \ DISPATCH_TO(*REGS.pc | activation.opMask()); \ JS_END_MACRO/* * Shorthand for the common sequence at the end of a fixed-size opcode. */#define END_CASE(OP) ADVANCE_AND_DISPATCH(OP##_LENGTH);/* * Prepare to call a user-supplied branch handler, and abort the script * if it returns false. */#define CHECK_BRANCH() \ JS_BEGIN_MACRO \ if (!CheckForInterrupt(cx)) \ goto error; \ JS_END_MACRO/* * This is a simple wrapper around ADVANCE_AND_DISPATCH which also does * a CHECK_BRANCH() if n is not positive, which possibly indicates that it * is the backedge of a loop. */#define BRANCH(n) \ JS_BEGIN_MACRO \ int32_t nlen = (n); \ if (nlen <= 0) \ CHECK_BRANCH(); \ ADVANCE_AND_DISPATCH(nlen); \ JS_END_MACRO/* * Initialize code coverage vectors. */#define INIT_COVERAGE() \ JS_BEGIN_MACRO \ if (!script->hasScriptCounts()) { \ if (cx->compartment()->collectCoverageForDebug()) { \ if (!script->initScriptCounts(cx)) \ goto error; \ } \ } \ JS_END_MACRO/* * Increment the code coverage counter associated with the given pc. */#define COUNT_COVERAGE_PC(PC) \ JS_BEGIN_MACRO \ if (script->hasScriptCounts()) { \ PCCounts* counts = script->maybeGetPCCounts(PC); \ MOZ_ASSERT(counts); \ counts->numExec()++; \ } \ JS_END_MACRO#define COUNT_COVERAGE_MAIN() \ JS_BEGIN_MACRO \ jsbytecode* main = script->main(); \ if (!BytecodeIsJumpTarget(JSOp(*main))) \ COUNT_COVERAGE_PC(main); \ JS_END_MACRO#define COUNT_COVERAGE() \ JS_BEGIN_MACRO \ MOZ_ASSERT(BytecodeIsJumpTarget(JSOp(*REGS.pc))); \ COUNT_COVERAGE_PC(REGS.pc); \ JS_END_MACRO#define LOAD_DOUBLE(PCOFF, dbl) \ ((dbl) = script->getConst(GET_UINT32_INDEX(REGS.pc + (PCOFF))).toDouble())#define SET_SCRIPT(s) \ JS_BEGIN_MACRO \ script = (s); \ if (script->hasAnyBreakpointsOrStepMode() || script->hasScriptCounts()) \ activation.enableInterruptsUnconditionally(); \ JS_END_MACRO#define SANITY_CHECKS() \ JS_BEGIN_MACRO \ js::gc::MaybeVerifyBarriers(cx); \ JS_END_MACROgc::MaybeVerifyBarriers(cx,true);MOZ_ASSERT(!cx->zone()->types.activeAnalysis);InterpreterFrame*entryFrame=state.pushInterpreterFrame(cx);if(!entryFrame)returnfalse;ActivationEntryMonitorentryMonitor(cx,entryFrame);InterpreterActivationactivation(state,cx,entryFrame);/* The script is used frequently, so keep a local copy. */RootedScriptscript(cx);SET_SCRIPT(REGS.fp()->script());TraceLoggerThread*logger=TraceLoggerForCurrentThread(cx);TraceLoggerEventscriptEvent(TraceLogger_Scripts,script);TraceLogStartEvent(logger,scriptEvent);TraceLogStartEvent(logger,TraceLogger_Interpreter);/* * Pool of rooters for use in this interpreter frame. References to these * are used for local variables within interpreter cases. This avoids * creating new rooters each time an interpreter case is entered, and also * correctness pitfalls due to incorrect compilation of destructor calls * around computed gotos. */RootedValuerootValue0(cx),rootValue1(cx);RootedStringrootString0(cx),rootString1(cx);RootedObjectrootObject0(cx),rootObject1(cx),rootObject2(cx);RootedNativeObjectrootNativeObject0(cx);RootedFunctionrootFunction0(cx);RootedPropertyNamerootName0(cx);RootedIdrootId0(cx);RootedShaperootShape0(cx);RootedScriptrootScript0(cx);Rooted<Scope*>rootScope0(cx);DebugOnly<uint32_t>blockDepth;/* State communicated between non-local jumps: */boolinterpReturnOK;boolframeHalfInitialized;if(!activation.entryFrame()->prologue(cx))gotoprologue_error;switch(Debugger::onEnterFrame(cx,activation.entryFrame())){caseJSTRAP_CONTINUE:break;caseJSTRAP_RETURN:if(!ForcedReturn(cx,REGS))gotoerror;gotosuccessful_return_continuation;caseJSTRAP_THROW:caseJSTRAP_ERROR:gotoerror;default:MOZ_CRASH("bad Debugger::onEnterFrame status");}// Increment the coverage for the main entry point.INIT_COVERAGE();COUNT_COVERAGE_MAIN();// Enter the interpreter loop starting at the current pc.ADVANCE_AND_DISPATCH(0);INTERPRETER_LOOP(){CASE(EnableInterruptsPseudoOpcode){boolmoreInterrupts=false;jsbytecodeop=*REGS.pc;if(!script->hasScriptCounts()&&cx->compartment()->collectCoverageForDebug()){if(!script->initScriptCounts(cx))gotoerror;}if(script->isDebuggee()){if(script->stepModeEnabled()){RootedValuerval(cx);JSTrapStatusstatus=JSTRAP_CONTINUE;status=Debugger::onSingleStep(cx,&rval);switch(status){caseJSTRAP_ERROR:gotoerror;caseJSTRAP_CONTINUE:break;caseJSTRAP_RETURN:REGS.fp()->setReturnValue(rval);if(!ForcedReturn(cx,REGS))gotoerror;gotosuccessful_return_continuation;caseJSTRAP_THROW:cx->setPendingException(rval);gotoerror;default:;}moreInterrupts=true;}if(script->hasAnyBreakpointsOrStepMode())moreInterrupts=true;if(script->hasBreakpointsAt(REGS.pc)){RootedValuerval(cx);JSTrapStatusstatus=Debugger::onTrap(cx,&rval);switch(status){caseJSTRAP_ERROR:gotoerror;caseJSTRAP_RETURN:REGS.fp()->setReturnValue(rval);if(!ForcedReturn(cx,REGS))gotoerror;gotosuccessful_return_continuation;caseJSTRAP_THROW:cx->setPendingException(rval);gotoerror;default:break;}MOZ_ASSERT(status==JSTRAP_CONTINUE);MOZ_ASSERT(rval.isInt32()&&rval.toInt32()==op);}}MOZ_ASSERT(activation.opMask()==EnableInterruptsPseudoOpcode);if(!moreInterrupts)activation.clearInterruptsMask();/* Commence executing the actual opcode. */SANITY_CHECKS();DISPATCH_TO(op);}/* Various 1-byte no-ops. */CASE(JSOP_NOP)CASE(JSOP_NOP_DESTRUCTURING)CASE(JSOP_TRY_DESTRUCTURING_ITERCLOSE)CASE(JSOP_UNUSED222)CASE(JSOP_UNUSED223)CASE(JSOP_CONDSWITCH){MOZ_ASSERT(CodeSpec[*REGS.pc].length==1);ADVANCE_AND_DISPATCH(1);}CASE(JSOP_TRY)CASE(JSOP_JUMPTARGET)CASE(JSOP_LOOPHEAD){MOZ_ASSERT(CodeSpec[*REGS.pc].length==1);COUNT_COVERAGE();ADVANCE_AND_DISPATCH(1);}CASE(JSOP_LABEL)END_CASE(JSOP_LABEL)CASE(JSOP_LOOPENTRY)COUNT_COVERAGE();// Attempt on-stack replacement with Baseline code.if(jit::IsBaselineEnabled(cx)){jit::MethodStatusstatus=jit::CanEnterBaselineAtBranch(cx,REGS.fp(),false);if(status==jit::Method_Error)gotoerror;if(status==jit::Method_Compiled){boolwasProfiler=REGS.fp()->hasPushedGeckoProfilerFrame();jit::JitExecStatusmaybeOsr;{GeckoProfilerBaselineOSRMarkerosr(cx->runtime(),wasProfiler);maybeOsr=jit::EnterBaselineAtBranch(cx,REGS.fp(),REGS.pc);}// We failed to call into baseline at all, so treat as an error.if(maybeOsr==jit::JitExec_Aborted)gotoerror;interpReturnOK=(maybeOsr==jit::JitExec_Ok);// Pop the profiler frame pushed by the interpreter. (The compiled// version of the function popped a copy of the frame pushed by the// OSR trampoline.)if(wasProfiler)cx->runtime()->geckoProfiler().exit(script,script->functionNonDelazifying());if(activation.entryFrame()!=REGS.fp())gotojit_return_pop_frame;gotoleave_on_safe_point;}}END_CASE(JSOP_LOOPENTRY)CASE(JSOP_LINENO)END_CASE(JSOP_LINENO)CASE(JSOP_FORCEINTERPRETER)END_CASE(JSOP_FORCEINTERPRETER)CASE(JSOP_UNDEFINED)// If this ever changes, change what JSOP_GIMPLICITTHIS does too.PUSH_UNDEFINED();END_CASE(JSOP_UNDEFINED)CASE(JSOP_POP)REGS.sp--;END_CASE(JSOP_POP)CASE(JSOP_POPN)MOZ_ASSERT(GET_UINT16(REGS.pc)<=REGS.stackDepth());REGS.sp-=GET_UINT16(REGS.pc);END_CASE(JSOP_POPN)CASE(JSOP_DUPAT){MOZ_ASSERT(GET_UINT24(REGS.pc)<REGS.stackDepth());unsignedi=GET_UINT24(REGS.pc);constValue&rref=REGS.sp[-int(i+1)];PUSH_COPY(rref);}END_CASE(JSOP_DUPAT)CASE(JSOP_SETRVAL)POP_RETURN_VALUE();END_CASE(JSOP_SETRVAL)CASE(JSOP_GETRVAL)PUSH_COPY(REGS.fp()->returnValue());END_CASE(JSOP_GETRVAL)CASE(JSOP_ENTERWITH){ReservedRooted<Value>val(&rootValue0,REGS.sp[-1]);REGS.sp--;ReservedRooted<Scope*>scope(&rootScope0,script->getScope(REGS.pc));if(!EnterWithOperation(cx,REGS.fp(),val,scope.as<WithScope>()))gotoerror;}END_CASE(JSOP_ENTERWITH)CASE(JSOP_LEAVEWITH)REGS.fp()->popOffEnvironmentChain<WithEnvironmentObject>();END_CASE(JSOP_LEAVEWITH)CASE(JSOP_RETURN)POP_RETURN_VALUE();/* FALL THROUGH */CASE(JSOP_RETRVAL){/* * When the inlined frame exits with an exception or an error, ok will be * false after the inline_return label. */CHECK_BRANCH();successful_return_continuation:interpReturnOK=true;return_continuation:frameHalfInitialized=false;prologue_return_continuation:if(activation.entryFrame()!=REGS.fp()){// Stop the engine. (No details about which engine exactly, could be// interpreter, Baseline or IonMonkey.)TraceLogStopEvent(logger,TraceLogger_Engine);TraceLogStopEvent(logger,TraceLogger_Scripts);if(MOZ_LIKELY(!frameHalfInitialized)){interpReturnOK=Debugger::onLeaveFrame(cx,REGS.fp(),REGS.pc,interpReturnOK);REGS.fp()->epilogue(cx,REGS.pc);}jit_return_pop_frame:activation.popInlineFrame(REGS.fp());SET_SCRIPT(REGS.fp()->script());jit_return:MOZ_ASSERT(CodeSpec[*REGS.pc].format&JOF_INVOKE);/* Resume execution in the calling frame. */if(MOZ_LIKELY(interpReturnOK)){TypeScript::Monitor(cx,script,REGS.pc,REGS.sp[-1]);ADVANCE_AND_DISPATCH(JSOP_CALL_LENGTH);}gotoerror;}else{MOZ_ASSERT(REGS.stackDepth()==0);}gotoexit;}CASE(JSOP_DEFAULT)REGS.sp--;/* FALL THROUGH */CASE(JSOP_GOTO){BRANCH(GET_JUMP_OFFSET(REGS.pc));}CASE(JSOP_IFEQ){boolcond=ToBoolean(REGS.stackHandleAt(-1));REGS.sp--;if(!cond)BRANCH(GET_JUMP_OFFSET(REGS.pc));}END_CASE(JSOP_IFEQ)CASE(JSOP_IFNE){boolcond=ToBoolean(REGS.stackHandleAt(-1));REGS.sp--;if(cond)BRANCH(GET_JUMP_OFFSET(REGS.pc));}END_CASE(JSOP_IFNE)CASE(JSOP_OR){boolcond=ToBoolean(REGS.stackHandleAt(-1));if(cond)ADVANCE_AND_DISPATCH(GET_JUMP_OFFSET(REGS.pc));}END_CASE(JSOP_OR)CASE(JSOP_AND){boolcond=ToBoolean(REGS.stackHandleAt(-1));if(!cond)ADVANCE_AND_DISPATCH(GET_JUMP_OFFSET(REGS.pc));}END_CASE(JSOP_AND)#define FETCH_ELEMENT_ID(n, id) \ JS_BEGIN_MACRO \ if (!ToPropertyKey(cx, REGS.stackHandleAt(n), &(id))) \ goto error; \ JS_END_MACRO#define TRY_BRANCH_AFTER_COND(cond,spdec) \ JS_BEGIN_MACRO \ MOZ_ASSERT(CodeSpec[*REGS.pc].length == 1); \ unsigned diff_ = (unsigned) GET_UINT8(REGS.pc) - (unsigned) JSOP_IFEQ; \ if (diff_ <= 1) { \ REGS.sp -= (spdec); \ if ((cond) == (diff_ != 0)) { \ ++REGS.pc; \ BRANCH(GET_JUMP_OFFSET(REGS.pc)); \ } \ ADVANCE_AND_DISPATCH(1 + JSOP_IFEQ_LENGTH); \ } \ JS_END_MACROCASE(JSOP_IN){HandleValuerref=REGS.stackHandleAt(-1);if(!rref.isObject()){ReportValueError(cx,JSMSG_IN_NOT_OBJECT,-1,rref,nullptr);gotoerror;}boolfound;{ReservedRooted<JSObject*>obj(&rootObject0,&rref.toObject());ReservedRooted<jsid>id(&rootId0);FETCH_ELEMENT_ID(-2,id);if(!HasProperty(cx,obj,id,&found))gotoerror;}TRY_BRANCH_AFTER_COND(found,2);REGS.sp--;REGS.sp[-1].setBoolean(found);}END_CASE(JSOP_IN)CASE(JSOP_HASOWN){HandleValueval=REGS.stackHandleAt(-1);HandleValueidval=REGS.stackHandleAt(-2);boolfound;if(!HasOwnProperty(cx,val,idval,&found))gotoerror;REGS.sp--;REGS.sp[-1].setBoolean(found);}END_CASE(JSOP_HASOWN)CASE(JSOP_ITER){MOZ_ASSERT(REGS.stackDepth()>=1);uint8_tflags=GET_UINT8(REGS.pc);HandleValueval=REGS.stackHandleAt(-1);ReservedRooted<JSObject*>iter(&rootObject0);iter.set(ValueToIterator(cx,flags,val));if(!iter)gotoerror;REGS.sp[-1].setObject(*iter);}END_CASE(JSOP_ITER)CASE(JSOP_MOREITER){MOZ_ASSERT(REGS.stackDepth()>=1);MOZ_ASSERT(REGS.sp[-1].isObject());PUSH_NULL();ReservedRooted<JSObject*>obj(&rootObject0,®S.sp[-2].toObject());if(!IteratorMore(cx,obj,REGS.stackHandleAt(-1)))gotoerror;}END_CASE(JSOP_MOREITER)CASE(JSOP_ISNOITER){boolb=REGS.sp[-1].isMagic(JS_NO_ITER_VALUE);PUSH_BOOLEAN(b);}END_CASE(JSOP_ISNOITER)CASE(JSOP_ENDITER){MOZ_ASSERT(REGS.stackDepth()>=1);COUNT_COVERAGE();ReservedRooted<JSObject*>obj(&rootObject0,®S.sp[-1].toObject());boolok=CloseIterator(cx,obj);REGS.sp--;if(!ok)gotoerror;}END_CASE(JSOP_ENDITER)CASE(JSOP_ISGENCLOSING){boolb=REGS.sp[-1].isMagic(JS_GENERATOR_CLOSING);PUSH_BOOLEAN(b);}END_CASE(JSOP_ISGENCLOSING)CASE(JSOP_DUP){MOZ_ASSERT(REGS.stackDepth()>=1);constValue&rref=REGS.sp[-1];PUSH_COPY(rref);}END_CASE(JSOP_DUP)CASE(JSOP_DUP2){MOZ_ASSERT(REGS.stackDepth()>=2);constValue&lref=REGS.sp[-2];constValue&rref=REGS.sp[-1];PUSH_COPY(lref);PUSH_COPY(rref);}END_CASE(JSOP_DUP2)CASE(JSOP_SWAP){MOZ_ASSERT(REGS.stackDepth()>=2);Value&lref=REGS.sp[-2];Value&rref=REGS.sp[-1];lref.swap(rref);}END_CASE(JSOP_SWAP)CASE(JSOP_PICK){unsignedi=GET_UINT8(REGS.pc);MOZ_ASSERT(REGS.stackDepth()>=i+1);Valuelval=REGS.sp[-int(i+1)];memmove(REGS.sp-(i+1),REGS.sp-i,sizeof(Value)*i);REGS.sp[-1]=lval;}END_CASE(JSOP_PICK)CASE(JSOP_UNPICK){inti=GET_UINT8(REGS.pc);MOZ_ASSERT(REGS.stackDepth()>=unsigned(i)+1);Valuelval=REGS.sp[-1];memmove(REGS.sp-i,REGS.sp-(i+1),sizeof(Value)*i);REGS.sp[-(i+1)]=lval;}END_CASE(JSOP_UNPICK)CASE(JSOP_BINDGNAME)CASE(JSOP_BINDNAME){JSOpop=JSOp(*REGS.pc);ReservedRooted<JSObject*>envChain(&rootObject0);if(op==JSOP_BINDNAME||script->hasNonSyntacticScope())envChain.set(REGS.fp()->environmentChain());elseenvChain.set(®S.fp()->global().lexicalEnvironment());ReservedRooted<PropertyName*>name(&rootName0,script->getName(REGS.pc));/* Assigning to an undeclared name adds a property to the global object. */ReservedRooted<JSObject*>env(&rootObject1);if(!LookupNameUnqualified(cx,name,envChain,&env))gotoerror;PUSH_OBJECT(*env);static_assert(JSOP_BINDNAME_LENGTH==JSOP_BINDGNAME_LENGTH,"We're sharing the END_CASE so the lengths better match");}END_CASE(JSOP_BINDNAME)CASE(JSOP_BINDVAR){PUSH_OBJECT(REGS.fp()->varObj());}END_CASE(JSOP_BINDVAR)#define BITWISE_OP(OP) \ JS_BEGIN_MACRO \ int32_t i, j; \ if (!ToInt32(cx, REGS.stackHandleAt(-2), &i)) \ goto error; \ if (!ToInt32(cx, REGS.stackHandleAt(-1), &j)) \ goto error; \ i = i OP j; \ REGS.sp--; \ REGS.sp[-1].setInt32(i); \ JS_END_MACROCASE(JSOP_BITOR)BITWISE_OP(|);END_CASE(JSOP_BITOR)CASE(JSOP_BITXOR)BITWISE_OP(^);END_CASE(JSOP_BITXOR)CASE(JSOP_BITAND)BITWISE_OP(&);END_CASE(JSOP_BITAND)#undef BITWISE_OPCASE(JSOP_EQ)if(!LooseEqualityOp<true>(cx,REGS))gotoerror;END_CASE(JSOP_EQ)CASE(JSOP_NE)if(!LooseEqualityOp<false>(cx,REGS))gotoerror;END_CASE(JSOP_NE)#define STRICT_EQUALITY_OP(OP, COND) \ JS_BEGIN_MACRO \ HandleValue lval = REGS.stackHandleAt(-2); \ HandleValue rval = REGS.stackHandleAt(-1); \ bool equal; \ if (!StrictlyEqual(cx, lval, rval, &equal)) \ goto error; \ (COND) = equal OP true; \ REGS.sp--; \ JS_END_MACROCASE(JSOP_STRICTEQ){boolcond;STRICT_EQUALITY_OP(==,cond);REGS.sp[-1].setBoolean(cond);}END_CASE(JSOP_STRICTEQ)CASE(JSOP_STRICTNE){boolcond;STRICT_EQUALITY_OP(!=,cond);REGS.sp[-1].setBoolean(cond);}END_CASE(JSOP_STRICTNE)CASE(JSOP_CASE){boolcond;STRICT_EQUALITY_OP(==,cond);if(cond){REGS.sp--;BRANCH(GET_JUMP_OFFSET(REGS.pc));}}END_CASE(JSOP_CASE)#undef STRICT_EQUALITY_OPCASE(JSOP_LT){boolcond;MutableHandleValuelval=REGS.stackHandleAt(-2);MutableHandleValuerval=REGS.stackHandleAt(-1);if(!LessThanOperation(cx,lval,rval,&cond))gotoerror;TRY_BRANCH_AFTER_COND(cond,2);REGS.sp[-2].setBoolean(cond);REGS.sp--;}END_CASE(JSOP_LT)CASE(JSOP_LE){boolcond;MutableHandleValuelval=REGS.stackHandleAt(-2);MutableHandleValuerval=REGS.stackHandleAt(-1);if(!LessThanOrEqualOperation(cx,lval,rval,&cond))gotoerror;TRY_BRANCH_AFTER_COND(cond,2);REGS.sp[-2].setBoolean(cond);REGS.sp--;}END_CASE(JSOP_LE)CASE(JSOP_GT){boolcond;MutableHandleValuelval=REGS.stackHandleAt(-2);MutableHandleValuerval=REGS.stackHandleAt(-1);if(!GreaterThanOperation(cx,lval,rval,&cond))gotoerror;TRY_BRANCH_AFTER_COND(cond,2);REGS.sp[-2].setBoolean(cond);REGS.sp--;}END_CASE(JSOP_GT)CASE(JSOP_GE){boolcond;MutableHandleValuelval=REGS.stackHandleAt(-2);MutableHandleValuerval=REGS.stackHandleAt(-1);if(!GreaterThanOrEqualOperation(cx,lval,rval,&cond))gotoerror;TRY_BRANCH_AFTER_COND(cond,2);REGS.sp[-2].setBoolean(cond);REGS.sp--;}END_CASE(JSOP_GE)#define SIGNED_SHIFT_OP(OP) \ JS_BEGIN_MACRO \ int32_t i, j; \ if (!ToInt32(cx, REGS.stackHandleAt(-2), &i)) \ goto error; \ if (!ToInt32(cx, REGS.stackHandleAt(-1), &j)) \ goto error; \ i = i OP (j & 31); \ REGS.sp--; \ REGS.sp[-1].setInt32(i); \ JS_END_MACROCASE(JSOP_LSH)SIGNED_SHIFT_OP(<<);END_CASE(JSOP_LSH)CASE(JSOP_RSH)SIGNED_SHIFT_OP(>>);END_CASE(JSOP_RSH)#undef SIGNED_SHIFT_OPCASE(JSOP_URSH){HandleValuelval=REGS.stackHandleAt(-2);HandleValuerval=REGS.stackHandleAt(-1);MutableHandleValueres=REGS.stackHandleAt(-2);if(!UrshOperation(cx,lval,rval,res))gotoerror;REGS.sp--;}END_CASE(JSOP_URSH)CASE(JSOP_ADD){MutableHandleValuelval=REGS.stackHandleAt(-2);MutableHandleValuerval=REGS.stackHandleAt(-1);MutableHandleValueres=REGS.stackHandleAt(-2);if(!AddOperation(cx,lval,rval,res))gotoerror;REGS.sp--;}END_CASE(JSOP_ADD)CASE(JSOP_SUB){ReservedRooted<Value>lval(&rootValue0,REGS.sp[-2]);ReservedRooted<Value>rval(&rootValue1,REGS.sp[-1]);MutableHandleValueres=REGS.stackHandleAt(-2);if(!SubOperation(cx,lval,rval,res))gotoerror;REGS.sp--;}END_CASE(JSOP_SUB)CASE(JSOP_MUL){ReservedRooted<Value>lval(&rootValue0,REGS.sp[-2]);ReservedRooted<Value>rval(&rootValue1,REGS.sp[-1]);MutableHandleValueres=REGS.stackHandleAt(-2);if(!MulOperation(cx,lval,rval,res))gotoerror;REGS.sp--;}END_CASE(JSOP_MUL)CASE(JSOP_DIV){ReservedRooted<Value>lval(&rootValue0,REGS.sp[-2]);ReservedRooted<Value>rval(&rootValue1,REGS.sp[-1]);MutableHandleValueres=REGS.stackHandleAt(-2);if(!DivOperation(cx,lval,rval,res))gotoerror;REGS.sp--;}END_CASE(JSOP_DIV)CASE(JSOP_MOD){ReservedRooted<Value>lval(&rootValue0,REGS.sp[-2]);ReservedRooted<Value>rval(&rootValue1,REGS.sp[-1]);MutableHandleValueres=REGS.stackHandleAt(-2);if(!ModOperation(cx,lval,rval,res))gotoerror;REGS.sp--;}END_CASE(JSOP_MOD)CASE(JSOP_POW){ReservedRooted<Value>lval(&rootValue0,REGS.sp[-2]);ReservedRooted<Value>rval(&rootValue1,REGS.sp[-1]);MutableHandleValueres=REGS.stackHandleAt(-2);if(!math_pow_handle(cx,lval,rval,res))gotoerror;REGS.sp--;}END_CASE(JSOP_POW)CASE(JSOP_NOT){boolcond=ToBoolean(REGS.stackHandleAt(-1));REGS.sp--;PUSH_BOOLEAN(!cond);}END_CASE(JSOP_NOT)CASE(JSOP_BITNOT){int32_ti;HandleValuevalue=REGS.stackHandleAt(-1);if(!BitNot(cx,value,&i))gotoerror;REGS.sp[-1].setInt32(i);}END_CASE(JSOP_BITNOT)CASE(JSOP_NEG){ReservedRooted<Value>val(&rootValue0,REGS.sp[-1]);MutableHandleValueres=REGS.stackHandleAt(-1);if(!NegOperation(cx,script,REGS.pc,val,res))gotoerror;}END_CASE(JSOP_NEG)CASE(JSOP_POS)if(!ToNumber(cx,REGS.stackHandleAt(-1)))gotoerror;END_CASE(JSOP_POS)CASE(JSOP_DELNAME){ReservedRooted<PropertyName*>name(&rootName0,script->getName(REGS.pc));ReservedRooted<JSObject*>envObj(&rootObject0,REGS.fp()->environmentChain());PUSH_BOOLEAN(true);MutableHandleValueres=REGS.stackHandleAt(-1);if(!DeleteNameOperation(cx,name,envObj,res))gotoerror;}END_CASE(JSOP_DELNAME)CASE(JSOP_DELPROP)CASE(JSOP_STRICTDELPROP){static_assert(JSOP_DELPROP_LENGTH==JSOP_STRICTDELPROP_LENGTH,"delprop and strictdelprop must be the same size");ReservedRooted<jsid>id(&rootId0,NameToId(script->getName(REGS.pc)));ReservedRooted<JSObject*>obj(&rootObject0);FETCH_OBJECT(cx,-1,obj);ObjectOpResultresult;if(!DeleteProperty(cx,obj,id,result))gotoerror;if(!result&&JSOp(*REGS.pc)==JSOP_STRICTDELPROP){result.reportError(cx,obj,id);gotoerror;}MutableHandleValueres=REGS.stackHandleAt(-1);res.setBoolean(result.ok());}END_CASE(JSOP_DELPROP)CASE(JSOP_DELELEM)CASE(JSOP_STRICTDELELEM){static_assert(JSOP_DELELEM_LENGTH==JSOP_STRICTDELELEM_LENGTH,"delelem and strictdelelem must be the same size");/* Fetch the left part and resolve it to a non-null object. */ReservedRooted<JSObject*>obj(&rootObject0);FETCH_OBJECT(cx,-2,obj);ReservedRooted<Value>propval(&rootValue0,REGS.sp[-1]);ObjectOpResultresult;ReservedRooted<jsid>id(&rootId0);if(!ToPropertyKey(cx,propval,&id))gotoerror;if(!DeleteProperty(cx,obj,id,result))gotoerror;if(!result&&JSOp(*REGS.pc)==JSOP_STRICTDELELEM){result.reportError(cx,obj,id);gotoerror;}MutableHandleValueres=REGS.stackHandleAt(-2);res.setBoolean(result.ok());REGS.sp--;}END_CASE(JSOP_DELELEM)CASE(JSOP_TOID){/* * Increment or decrement requires use to lookup the same property twice, * but we need to avoid the observable stringification the second time. * There must be an object value below the id, which will not be popped. */ReservedRooted<Value>idval(&rootValue1,REGS.sp[-1]);MutableHandleValueres=REGS.stackHandleAt(-1);if(!ToIdOperation(cx,script,REGS.pc,idval,res))gotoerror;}END_CASE(JSOP_TOID)CASE(JSOP_TYPEOFEXPR)CASE(JSOP_TYPEOF){REGS.sp[-1].setString(TypeOfOperation(REGS.sp[-1],cx->runtime()));}END_CASE(JSOP_TYPEOF)CASE(JSOP_VOID)REGS.sp[-1].setUndefined();END_CASE(JSOP_VOID)CASE(JSOP_FUNCTIONTHIS)PUSH_NULL();if(!GetFunctionThis(cx,REGS.fp(),REGS.stackHandleAt(-1)))gotoerror;END_CASE(JSOP_FUNCTIONTHIS)CASE(JSOP_GLOBALTHIS){if(script->hasNonSyntacticScope()){PUSH_NULL();if(!GetNonSyntacticGlobalThis(cx,REGS.fp()->environmentChain(),REGS.stackHandleAt(-1)))gotoerror;}else{PUSH_COPY(cx->global()->lexicalEnvironment().thisValue());}}END_CASE(JSOP_GLOBALTHIS)CASE(JSOP_CHECKISOBJ){if(!REGS.sp[-1].isObject()){MOZ_ALWAYS_FALSE(ThrowCheckIsObject(cx,CheckIsObjectKind(GET_UINT8(REGS.pc))));gotoerror;}}END_CASE(JSOP_CHECKISOBJ)CASE(JSOP_CHECKISCALLABLE){if(!IsCallable(REGS.sp[-1])){MOZ_ALWAYS_FALSE(ThrowCheckIsCallable(cx,CheckIsCallableKind(GET_UINT8(REGS.pc))));gotoerror;}}END_CASE(JSOP_CHECKISCALLABLE)CASE(JSOP_CHECKTHIS){if(REGS.sp[-1].isMagic(JS_UNINITIALIZED_LEXICAL)){MOZ_ALWAYS_FALSE(ThrowUninitializedThis(cx,REGS.fp()));gotoerror;}}END_CASE(JSOP_CHECKTHIS)CASE(JSOP_CHECKTHISREINIT){if(!REGS.sp[-1].isMagic(JS_UNINITIALIZED_LEXICAL)){MOZ_ALWAYS_FALSE(ThrowInitializedThis(cx,REGS.fp()));gotoerror;}}END_CASE(JSOP_CHECKTHISREINIT)CASE(JSOP_CHECKRETURN){if(!REGS.fp()->checkReturn(cx,REGS.stackHandleAt(-1)))gotoerror;REGS.sp--;}END_CASE(JSOP_CHECKRETURN)CASE(JSOP_GETPROP)CASE(JSOP_LENGTH)CASE(JSOP_CALLPROP){MutableHandleValuelval=REGS.stackHandleAt(-1);if(!GetPropertyOperation(cx,REGS.fp(),script,REGS.pc,lval,lval))gotoerror;TypeScript::Monitor(cx,script,REGS.pc,lval);assertSameCompartmentDebugOnly(cx,lval);}END_CASE(JSOP_GETPROP)CASE(JSOP_GETPROP_SUPER){ReservedRooted<Value>receiver(&rootValue0,REGS.sp[-2]);ReservedRooted<JSObject*>obj(&rootObject1,®S.sp[-1].toObject());MutableHandleValuerref=REGS.stackHandleAt(-2);if(!GetProperty(cx,obj,receiver,script->getName(REGS.pc),rref))gotoerror;TypeScript::Monitor(cx,script,REGS.pc,rref);assertSameCompartmentDebugOnly(cx,rref);REGS.sp--;}END_CASE(JSOP_GETPROP_SUPER)CASE(JSOP_GETBOUNDNAME){ReservedRooted<JSObject*>env(&rootObject0,®S.sp[-1].toObject());ReservedRooted<jsid>id(&rootId0,NameToId(script->getName(REGS.pc)));MutableHandleValuerval=REGS.stackHandleAt(-1);if(!GetNameBoundInEnvironment(cx,env,id,rval))gotoerror;TypeScript::Monitor(cx,script,REGS.pc,rval);assertSameCompartmentDebugOnly(cx,rval);}END_CASE(JSOP_GETBOUNDNAME)CASE(JSOP_SETINTRINSIC){HandleValuevalue=REGS.stackHandleAt(-1);if(!SetIntrinsicOperation(cx,script,REGS.pc,value))gotoerror;}END_CASE(JSOP_SETINTRINSIC)CASE(JSOP_SETGNAME)CASE(JSOP_STRICTSETGNAME)CASE(JSOP_SETNAME)CASE(JSOP_STRICTSETNAME){static_assert(JSOP_SETNAME_LENGTH==JSOP_STRICTSETNAME_LENGTH,"setname and strictsetname must be the same size");static_assert(JSOP_SETGNAME_LENGTH==JSOP_STRICTSETGNAME_LENGTH,"setganem adn strictsetgname must be the same size");static_assert(JSOP_SETNAME_LENGTH==JSOP_SETGNAME_LENGTH,"We're sharing the END_CASE so the lengths better match");ReservedRooted<JSObject*>env(&rootObject0,®S.sp[-2].toObject());HandleValuevalue=REGS.stackHandleAt(-1);if(!SetNameOperation(cx,script,REGS.pc,env,value))gotoerror;REGS.sp[-2]=REGS.sp[-1];REGS.sp--;}END_CASE(JSOP_SETNAME)CASE(JSOP_SETPROP)CASE(JSOP_STRICTSETPROP){static_assert(JSOP_SETPROP_LENGTH==JSOP_STRICTSETPROP_LENGTH,"setprop and strictsetprop must be the same size");HandleValuelval=REGS.stackHandleAt(-2);HandleValuerval=REGS.stackHandleAt(-1);ReservedRooted<jsid>id(&rootId0,NameToId(script->getName(REGS.pc)));if(!SetPropertyOperation(cx,JSOp(*REGS.pc),lval,id,rval))gotoerror;REGS.sp[-2]=REGS.sp[-1];REGS.sp--;}END_CASE(JSOP_SETPROP)CASE(JSOP_SETPROP_SUPER)CASE(JSOP_STRICTSETPROP_SUPER){static_assert(JSOP_SETPROP_SUPER_LENGTH==JSOP_STRICTSETPROP_SUPER_LENGTH,"setprop-super and strictsetprop-super must be the same size");ReservedRooted<Value>receiver(&rootValue0,REGS.sp[-3]);ReservedRooted<JSObject*>obj(&rootObject0,®S.sp[-2].toObject());ReservedRooted<Value>rval(&rootValue1,REGS.sp[-1]);ReservedRooted<PropertyName*>name(&rootName0,script->getName(REGS.pc));boolstrict=JSOp(*REGS.pc)==JSOP_STRICTSETPROP_SUPER;if(!SetPropertySuper(cx,obj,receiver,name,rval,strict))gotoerror;REGS.sp[-3]=REGS.sp[-1];REGS.sp-=2;}END_CASE(JSOP_SETPROP_SUPER)CASE(JSOP_GETELEM)CASE(JSOP_CALLELEM){MutableHandleValuelval=REGS.stackHandleAt(-2);HandleValuerval=REGS.stackHandleAt(-1);MutableHandleValueres=REGS.stackHandleAt(-2);booldone=false;if(!GetElemOptimizedArguments(cx,REGS.fp(),lval,rval,res,&done))gotoerror;if(!done){if(!GetElementOperation(cx,JSOp(*REGS.pc),lval,rval,res))gotoerror;}TypeScript::Monitor(cx,script,REGS.pc,res);REGS.sp--;}END_CASE(JSOP_GETELEM)CASE(JSOP_GETELEM_SUPER){ReservedRooted<Value>rval(&rootValue0,REGS.sp[-3]);ReservedRooted<Value>receiver(&rootValue1,REGS.sp[-2]);ReservedRooted<JSObject*>obj(&rootObject1,®S.sp[-1].toObject());MutableHandleValueres=REGS.stackHandleAt(-3);// Since we have asserted that obj has to be an object, it cannot be// either optimized arguments, or indeed any primitive. This simplifies// our task some.if(!GetObjectElementOperation(cx,JSOp(*REGS.pc),obj,receiver,rval,res))gotoerror;TypeScript::Monitor(cx,script,REGS.pc,res);REGS.sp-=2;}END_CASE(JSOP_GETELEM_SUPER)CASE(JSOP_SETELEM)CASE(JSOP_STRICTSETELEM){static_assert(JSOP_SETELEM_LENGTH==JSOP_STRICTSETELEM_LENGTH,"setelem and strictsetelem must be the same size");HandleValuereceiver=REGS.stackHandleAt(-3);ReservedRooted<JSObject*>obj(&rootObject0);obj=ToObjectFromStack(cx,receiver);if(!obj)gotoerror;ReservedRooted<jsid>id(&rootId0);FETCH_ELEMENT_ID(-2,id);HandleValuevalue=REGS.stackHandleAt(-1);if(!SetObjectElementOperation(cx,obj,id,value,receiver,*REGS.pc==JSOP_STRICTSETELEM))gotoerror;REGS.sp[-3]=value;REGS.sp-=2;}END_CASE(JSOP_SETELEM)CASE(JSOP_SETELEM_SUPER)CASE(JSOP_STRICTSETELEM_SUPER){static_assert(JSOP_SETELEM_SUPER_LENGTH==JSOP_STRICTSETELEM_SUPER_LENGTH,"setelem-super and strictsetelem-super must be the same size");ReservedRooted<Value>index(&rootValue1,REGS.sp[-4]);ReservedRooted<Value>receiver(&rootValue0,REGS.sp[-3]);ReservedRooted<JSObject*>obj(&rootObject1,®S.sp[-2].toObject());HandleValuevalue=REGS.stackHandleAt(-1);boolstrict=JSOp(*REGS.pc)==JSOP_STRICTSETELEM_SUPER;if(!SetObjectElement(cx,obj,index,value,receiver,strict))gotoerror;REGS.sp[-4]=value;REGS.sp-=3;}END_CASE(JSOP_SETELEM_SUPER)CASE(JSOP_EVAL)CASE(JSOP_STRICTEVAL){static_assert(JSOP_EVAL_LENGTH==JSOP_STRICTEVAL_LENGTH,"eval and stricteval must be the same size");CallArgsargs=CallArgsFromSp(GET_ARGC(REGS.pc),REGS.sp);if(REGS.fp()->environmentChain()->global().valueIsEval(args.calleev())){if(!DirectEval(cx,args.get(0),args.rval()))gotoerror;}else{if(!CallFromStack(cx,args))gotoerror;}REGS.sp=args.spAfterCall();TypeScript::Monitor(cx,script,REGS.pc,REGS.sp[-1]);}END_CASE(JSOP_EVAL)CASE(JSOP_SPREADNEW)CASE(JSOP_SPREADCALL)CASE(JSOP_SPREADSUPERCALL)if(REGS.fp()->hasPushedGeckoProfilerFrame())cx->runtime()->geckoProfiler().updatePC(script,REGS.pc);/* FALL THROUGH */CASE(JSOP_SPREADEVAL)CASE(JSOP_STRICTSPREADEVAL){static_assert(JSOP_SPREADEVAL_LENGTH==JSOP_STRICTSPREADEVAL_LENGTH,"spreadeval and strictspreadeval must be the same size");boolconstruct=JSOp(*REGS.pc)==JSOP_SPREADNEW||JSOp(*REGS.pc)==JSOP_SPREADSUPERCALL;;MOZ_ASSERT(REGS.stackDepth()>=3u+construct);HandleValuecallee=REGS.stackHandleAt(-3-construct);HandleValuethisv=REGS.stackHandleAt(-2-construct);HandleValuearr=REGS.stackHandleAt(-1-construct);MutableHandleValueret=REGS.stackHandleAt(-3-construct);RootedValue&newTarget=rootValue0;if(construct)newTarget=REGS.sp[-1];elsenewTarget=NullValue();if(!SpreadCallOperation(cx,script,REGS.pc,thisv,callee,arr,newTarget,ret))gotoerror;REGS.sp-=2+construct;}END_CASE(JSOP_SPREADCALL)CASE(JSOP_FUNAPPLY){CallArgsargs=CallArgsFromSp(GET_ARGC(REGS.pc),REGS.sp);if(!GuardFunApplyArgumentsOptimization(cx,REGS.fp(),args))gotoerror;/* FALL THROUGH */}CASE(JSOP_NEW)CASE(JSOP_CALL)CASE(JSOP_CALL_IGNORES_RV)CASE(JSOP_CALLITER)CASE(JSOP_SUPERCALL)CASE(JSOP_FUNCALL){if(REGS.fp()->hasPushedGeckoProfilerFrame())cx->runtime()->geckoProfiler().updatePC(script,REGS.pc);MaybeConstructconstruct=MaybeConstruct(*REGS.pc==JSOP_NEW||*REGS.pc==JSOP_SUPERCALL);boolignoresReturnValue=*REGS.pc==JSOP_CALL_IGNORES_RV;unsignedargStackSlots=GET_ARGC(REGS.pc)+construct;MOZ_ASSERT(REGS.stackDepth()>=2u+GET_ARGC(REGS.pc));CallArgsargs=CallArgsFromSp(argStackSlots,REGS.sp,construct,ignoresReturnValue);JSFunction*maybeFun;boolisFunction=IsFunctionObject(args.calleev(),&maybeFun);/* Don't bother trying to fast-path calls to scripted non-constructors. */if(!isFunction||!maybeFun->isInterpreted()||!maybeFun->isConstructor()||(!construct&&maybeFun->isClassConstructor())){if(construct){if(!ConstructFromStack(cx,args))gotoerror;}else{if(*REGS.pc==JSOP_CALLITER&&args.calleev().isPrimitive()){MOZ_ASSERT(args.length()==0,"thisv must be on top of the stack");ReportValueError(cx,JSMSG_NOT_ITERABLE,-1,args.thisv(),nullptr);gotoerror;}if(!CallFromStack(cx,args))gotoerror;}Value*newsp=args.spAfterCall();TypeScript::Monitor(cx,script,REGS.pc,newsp[-1]);REGS.sp=newsp;ADVANCE_AND_DISPATCH(JSOP_CALL_LENGTH);}{MOZ_ASSERT(maybeFun);ReservedRooted<JSFunction*>fun(&rootFunction0,maybeFun);ReservedRooted<JSScript*>funScript(&rootScript0,JSFunction::getOrCreateScript(cx,fun));if(!funScript)gotoerror;boolcreateSingleton=ObjectGroup::useSingletonForNewObject(cx,script,REGS.pc);TypeMonitorCall(cx,args,construct);mozilla::Maybe<InvokeState>state;state.emplace(cx,args,construct);if(createSingleton)state->setCreateSingleton();if(!createSingleton&&jit::IsIonEnabled(cx)){jit::MethodStatusstatus=jit::CanEnter(cx,state.ref());if(status==jit::Method_Error)gotoerror;if(status==jit::Method_Compiled){jit::JitExecStatusexec=jit::IonCannon(cx,state.ref());interpReturnOK=!IsErrorStatus(exec);if(interpReturnOK)CHECK_BRANCH();REGS.sp=args.spAfterCall();gotojit_return;}}if(jit::IsBaselineEnabled(cx)){jit::MethodStatusstatus=jit::CanEnterBaselineMethod(cx,state.ref());if(status==jit::Method_Error)gotoerror;if(status==jit::Method_Compiled){jit::JitExecStatusexec=jit::EnterBaselineMethod(cx,state.ref());interpReturnOK=!IsErrorStatus(exec);if(interpReturnOK)CHECK_BRANCH();REGS.sp=args.spAfterCall();gotojit_return;}}state.reset();funScript=fun->nonLazyScript();if(!activation.pushInlineFrame(args,funScript,construct))gotoerror;if(createSingleton)REGS.fp()->setCreateSingleton();}SET_SCRIPT(REGS.fp()->script());{TraceLoggerEventevent(TraceLogger_Scripts,script);TraceLogStartEvent(logger,event);TraceLogStartEvent(logger,TraceLogger_Interpreter);}if(!REGS.fp()->prologue(cx))gotoprologue_error;switch(Debugger::onEnterFrame(cx,REGS.fp())){caseJSTRAP_CONTINUE:break;caseJSTRAP_RETURN:if(!ForcedReturn(cx,REGS))gotoerror;gotosuccessful_return_continuation;caseJSTRAP_THROW:caseJSTRAP_ERROR:gotoerror;default:MOZ_CRASH("bad Debugger::onEnterFrame status");}// Increment the coverage for the main entry point.INIT_COVERAGE();COUNT_COVERAGE_MAIN();/* Load first op and dispatch it (safe since JSOP_RETRVAL). */ADVANCE_AND_DISPATCH(0);}CASE(JSOP_OPTIMIZE_SPREADCALL){ReservedRooted<Value>val(&rootValue0,REGS.sp[-1]);booloptimized=false;if(!OptimizeSpreadCall(cx,val,&optimized))gotoerror;PUSH_BOOLEAN(optimized);}END_CASE(JSOP_OPTIMIZE_SPREADCALL)CASE(JSOP_THROWMSG){JS_ALWAYS_FALSE(ThrowMsgOperation(cx,GET_UINT16(REGS.pc)));gotoerror;}END_CASE(JSOP_THROWMSG)CASE(JSOP_IMPLICITTHIS)CASE(JSOP_GIMPLICITTHIS){JSOpop=JSOp(*REGS.pc);if(op==JSOP_IMPLICITTHIS||script->hasNonSyntacticScope()){ReservedRooted<PropertyName*>name(&rootName0,script->getName(REGS.pc));ReservedRooted<JSObject*>envObj(&rootObject0,REGS.fp()->environmentChain());ReservedRooted<JSObject*>env(&rootObject1);if(!LookupNameWithGlobalDefault(cx,name,envObj,&env))gotoerror;Valuev=ComputeImplicitThis(env);PUSH_COPY(v);}else{// Treat it like JSOP_UNDEFINED.PUSH_UNDEFINED();}static_assert(JSOP_IMPLICITTHIS_LENGTH==JSOP_GIMPLICITTHIS_LENGTH,"We're sharing the END_CASE so the lengths better match");}END_CASE(JSOP_IMPLICITTHIS)CASE(JSOP_GETGNAME)CASE(JSOP_GETNAME){ReservedRooted<Value>rval(&rootValue0);if(!GetNameOperation(cx,REGS.fp(),REGS.pc,&rval))gotoerror;PUSH_COPY(rval);TypeScript::Monitor(cx,script,REGS.pc,rval);static_assert(JSOP_GETNAME_LENGTH==JSOP_GETGNAME_LENGTH,"We're sharing the END_CASE so the lengths better match");}END_CASE(JSOP_GETNAME)CASE(JSOP_GETIMPORT){PUSH_NULL();MutableHandleValuerval=REGS.stackHandleAt(-1);if(!GetImportOperation(cx,REGS.fp(),REGS.pc,rval))gotoerror;TypeScript::Monitor(cx,script,REGS.pc,rval);}END_CASE(JSOP_GETIMPORT)CASE(JSOP_GETINTRINSIC){ReservedRooted<Value>rval(&rootValue0);if(!GetIntrinsicOperation(cx,REGS.pc,&rval))gotoerror;PUSH_COPY(rval);TypeScript::Monitor(cx,script,REGS.pc,rval);}END_CASE(JSOP_GETINTRINSIC)CASE(JSOP_UINT16)PUSH_INT32((int32_t)GET_UINT16(REGS.pc));END_CASE(JSOP_UINT16)CASE(JSOP_UINT24)PUSH_INT32((int32_t)GET_UINT24(REGS.pc));END_CASE(JSOP_UINT24)CASE(JSOP_INT8)PUSH_INT32(GET_INT8(REGS.pc));END_CASE(JSOP_INT8)CASE(JSOP_INT32)PUSH_INT32(GET_INT32(REGS.pc));END_CASE(JSOP_INT32)CASE(JSOP_DOUBLE){doubledbl;LOAD_DOUBLE(0,dbl);PUSH_DOUBLE(dbl);}END_CASE(JSOP_DOUBLE)CASE(JSOP_STRING)PUSH_STRING(script->getAtom(REGS.pc));END_CASE(JSOP_STRING)CASE(JSOP_TOSTRING){MutableHandleValueoper=REGS.stackHandleAt(-1);if(!oper.isString()){JSString*operString=ToString<CanGC>(cx,oper);if(!operString)gotoerror;oper.setString(operString);}}END_CASE(JSOP_TOSTRING)CASE(JSOP_SYMBOL)PUSH_SYMBOL(cx->wellKnownSymbols().get(GET_UINT8(REGS.pc)));END_CASE(JSOP_SYMBOL)CASE(JSOP_OBJECT){ReservedRooted<JSObject*>ref(&rootObject0,script->getObject(REGS.pc));if(cx->compartment()->creationOptions().cloneSingletons()){JSObject*obj=DeepCloneObjectLiteral(cx,ref,TenuredObject);if(!obj)gotoerror;PUSH_OBJECT(*obj);}else{cx->compartment()->behaviors().setSingletonsAsValues();PUSH_OBJECT(*ref);}}END_CASE(JSOP_OBJECT)CASE(JSOP_CALLSITEOBJ){ReservedRooted<JSObject*>cso(&rootObject0,script->getObject(REGS.pc));ReservedRooted<JSObject*>raw(&rootObject1,script->getObject(GET_UINT32_INDEX(REGS.pc)+1));if(!cx->compartment()->getTemplateLiteralObject(cx,raw,&cso))gotoerror;PUSH_OBJECT(*cso);}END_CASE(JSOP_CALLSITEOBJ)CASE(JSOP_REGEXP){/* * Push a regexp object cloned from the regexp literal object mapped by the * bytecode at pc. */JSObject*obj=CloneRegExpObject(cx,script->getRegExp(REGS.pc));if(!obj)gotoerror;PUSH_OBJECT(*obj);}END_CASE(JSOP_REGEXP)CASE(JSOP_ZERO)PUSH_INT32(0);END_CASE(JSOP_ZERO)CASE(JSOP_ONE)PUSH_INT32(1);END_CASE(JSOP_ONE)CASE(JSOP_NULL)PUSH_NULL();END_CASE(JSOP_NULL)CASE(JSOP_FALSE)PUSH_BOOLEAN(false);END_CASE(JSOP_FALSE)CASE(JSOP_TRUE)PUSH_BOOLEAN(true);END_CASE(JSOP_TRUE)CASE(JSOP_TABLESWITCH){jsbytecode*pc2=REGS.pc;int32_tlen=GET_JUMP_OFFSET(pc2);/* * ECMAv2+ forbids conversion of discriminant, so we will skip to the * default case if the discriminant isn't already an int jsval. (This * opcode is emitted only for dense int-domain switches.) */constValue&rref=*--REGS.sp;int32_ti;if(rref.isInt32()){i=rref.toInt32();}else{/* Use mozilla::NumberEqualsInt32 to treat -0 (double) as 0. */if(!rref.isDouble()||!NumberEqualsInt32(rref.toDouble(),&i))ADVANCE_AND_DISPATCH(len);}pc2+=JUMP_OFFSET_LEN;int32_tlow=GET_JUMP_OFFSET(pc2);pc2+=JUMP_OFFSET_LEN;int32_thigh=GET_JUMP_OFFSET(pc2);i-=low;if((uint32_t)i<(uint32_t)(high-low+1)){pc2+=JUMP_OFFSET_LEN+JUMP_OFFSET_LEN*i;int32_toff=(int32_t)GET_JUMP_OFFSET(pc2);if(off)len=off;}ADVANCE_AND_DISPATCH(len);}CASE(JSOP_ARGUMENTS)if(!script->ensureHasAnalyzedArgsUsage(cx))gotoerror;if(script->needsArgsObj()){ArgumentsObject*obj=ArgumentsObject::createExpected(cx,REGS.fp());if(!obj)gotoerror;PUSH_COPY(ObjectValue(*obj));}else{PUSH_COPY(MagicValue(JS_OPTIMIZED_ARGUMENTS));}END_CASE(JSOP_ARGUMENTS)CASE(JSOP_RUNONCE){if(!RunOnceScriptPrologue(cx,script))gotoerror;}END_CASE(JSOP_RUNONCE)CASE(JSOP_REST){ReservedRooted<JSObject*>rest(&rootObject0,REGS.fp()->createRestParameter(cx));if(!rest)gotoerror;PUSH_COPY(ObjectValue(*rest));}END_CASE(JSOP_REST)CASE(JSOP_GETALIASEDVAR){EnvironmentCoordinateec=EnvironmentCoordinate(REGS.pc);ReservedRooted<Value>val(&rootValue0,REGS.fp()->aliasedEnvironment(ec).aliasedBinding(ec));#ifdef DEBUG// Only the .this slot can hold the TDZ MagicValue.if(IsUninitializedLexical(val)){PropertyName*name=EnvironmentCoordinateName(cx->caches().envCoordinateNameCache,script,REGS.pc);MOZ_ASSERT(name==cx->names().dotThis);JSOpnext=JSOp(*GetNextPc(REGS.pc));MOZ_ASSERT(next==JSOP_CHECKTHIS||next==JSOP_CHECKRETURN||next==JSOP_CHECKTHISREINIT);}#endifPUSH_COPY(val);TypeScript::Monitor(cx,script,REGS.pc,REGS.sp[-1]);}END_CASE(JSOP_GETALIASEDVAR)CASE(JSOP_SETALIASEDVAR){EnvironmentCoordinateec=EnvironmentCoordinate(REGS.pc);EnvironmentObject&obj=REGS.fp()->aliasedEnvironment(ec);SetAliasedVarOperation(cx,script,REGS.pc,obj,ec,REGS.sp[-1],CheckTDZ);}END_CASE(JSOP_SETALIASEDVAR)CASE(JSOP_THROWSETCONST)CASE(JSOP_THROWSETALIASEDCONST)CASE(JSOP_THROWSETCALLEE){ReportRuntimeConstAssignment(cx,script,REGS.pc);gotoerror;}END_CASE(JSOP_THROWSETCONST)CASE(JSOP_CHECKLEXICAL){uint32_ti=GET_LOCALNO(REGS.pc);ReservedRooted<Value>val(&rootValue0,REGS.fp()->unaliasedLocal(i));if(!CheckUninitializedLexical(cx,script,REGS.pc,val))gotoerror;}END_CASE(JSOP_CHECKLEXICAL)CASE(JSOP_INITLEXICAL){uint32_ti=GET_LOCALNO(REGS.pc);REGS.fp()->unaliasedLocal(i)=REGS.sp[-1];}END_CASE(JSOP_INITLEXICAL)CASE(JSOP_CHECKALIASEDLEXICAL){EnvironmentCoordinateec=EnvironmentCoordinate(REGS.pc);ReservedRooted<Value>val(&rootValue0,REGS.fp()->aliasedEnvironment(ec).aliasedBinding(ec));if(!CheckUninitializedLexical(cx,script,REGS.pc,val))gotoerror;}END_CASE(JSOP_CHECKALIASEDLEXICAL)CASE(JSOP_INITALIASEDLEXICAL){EnvironmentCoordinateec=EnvironmentCoordinate(REGS.pc);EnvironmentObject&obj=REGS.fp()->aliasedEnvironment(ec);SetAliasedVarOperation(cx,script,REGS.pc,obj,ec,REGS.sp[-1],DontCheckTDZ);}END_CASE(JSOP_INITALIASEDLEXICAL)CASE(JSOP_INITGLEXICAL){LexicalEnvironmentObject*lexicalEnv;if(script->hasNonSyntacticScope())lexicalEnv=®S.fp()->extensibleLexicalEnvironment();elselexicalEnv=&cx->global()->lexicalEnvironment();HandleValuevalue=REGS.stackHandleAt(-1);InitGlobalLexicalOperation(cx,lexicalEnv,script,REGS.pc,value);}END_CASE(JSOP_INITGLEXICAL)CASE(JSOP_UNINITIALIZED)PUSH_MAGIC(JS_UNINITIALIZED_LEXICAL);END_CASE(JSOP_UNINITIALIZED)CASE(JSOP_GETARG){unsignedi=GET_ARGNO(REGS.pc);if(script->argsObjAliasesFormals())PUSH_COPY(REGS.fp()->argsObj().arg(i));elsePUSH_COPY(REGS.fp()->unaliasedFormal(i));}END_CASE(JSOP_GETARG)CASE(JSOP_SETARG){unsignedi=GET_ARGNO(REGS.pc);if(script->argsObjAliasesFormals())REGS.fp()->argsObj().setArg(i,REGS.sp[-1]);elseREGS.fp()->unaliasedFormal(i)=REGS.sp[-1];}END_CASE(JSOP_SETARG)CASE(JSOP_GETLOCAL){uint32_ti=GET_LOCALNO(REGS.pc);PUSH_COPY_SKIP_CHECK(REGS.fp()->unaliasedLocal(i));#ifdef DEBUG// Derived class constructors store the TDZ Value in the .this slot// before a super() call.if(IsUninitializedLexical(REGS.sp[-1])){MOZ_ASSERT(script->isDerivedClassConstructor());JSOpnext=JSOp(*GetNextPc(REGS.pc));MOZ_ASSERT(next==JSOP_CHECKTHIS||next==JSOP_CHECKRETURN||next==JSOP_CHECKTHISREINIT);}#endif/* * Skip the same-compartment assertion if the local will be immediately * popped. We do not guarantee sync for dead locals when coming in from the * method JIT, and a GETLOCAL followed by POP is not considered to be * a use of the variable. */if(REGS.pc[JSOP_GETLOCAL_LENGTH]!=JSOP_POP)assertSameCompartmentDebugOnly(cx,REGS.sp[-1]);}END_CASE(JSOP_GETLOCAL)CASE(JSOP_SETLOCAL){uint32_ti=GET_LOCALNO(REGS.pc);MOZ_ASSERT(!IsUninitializedLexical(REGS.fp()->unaliasedLocal(i)));REGS.fp()->unaliasedLocal(i)=REGS.sp[-1];}END_CASE(JSOP_SETLOCAL)CASE(JSOP_DEFVAR){/* ES5 10.5 step 8 (with subsequent errata). */unsignedattrs=JSPROP_ENUMERATE;if(!REGS.fp()->isEvalFrame())attrs|=JSPROP_PERMANENT;/* Step 8b. */ReservedRooted<JSObject*>obj(&rootObject0,®S.fp()->varObj());ReservedRooted<PropertyName*>name(&rootName0,script->getName(REGS.pc));if(!DefVarOperation(cx,obj,name,attrs))gotoerror;}END_CASE(JSOP_DEFVAR)CASE(JSOP_DEFCONST)CASE(JSOP_DEFLET){LexicalEnvironmentObject*lexicalEnv;JSObject*varObj;if(script->hasNonSyntacticScope()){lexicalEnv=®S.fp()->extensibleLexicalEnvironment();varObj=®S.fp()->varObj();}else{lexicalEnv=&cx->global()->lexicalEnvironment();varObj=cx->global();}if(!DefLexicalOperation(cx,lexicalEnv,varObj,script,REGS.pc))gotoerror;}END_CASE(JSOP_DEFLET)CASE(JSOP_DEFFUN){/* * A top-level function defined in Global or Eval code (see ECMA-262 * Ed. 3), or else a SpiderMonkey extension: a named function statement in * a compound statement (not at the top statement level of global code, or * at the top level of a function body). */ReservedRooted<JSFunction*>fun(&rootFunction0,®S.sp[-1].toObject().as<JSFunction>());if(!DefFunOperation(cx,script,REGS.fp()->environmentChain(),fun))gotoerror;REGS.sp--;}END_CASE(JSOP_DEFFUN)CASE(JSOP_LAMBDA){/* Load the specified function object literal. */ReservedRooted<JSFunction*>fun(&rootFunction0,script->getFunction(GET_UINT32_INDEX(REGS.pc)));JSObject*obj=Lambda(cx,fun,REGS.fp()->environmentChain());if(!obj)gotoerror;MOZ_ASSERT(obj->staticPrototype());PUSH_OBJECT(*obj);}END_CASE(JSOP_LAMBDA)CASE(JSOP_LAMBDA_ARROW){/* Load the specified function object literal. */ReservedRooted<JSFunction*>fun(&rootFunction0,script->getFunction(GET_UINT32_INDEX(REGS.pc)));ReservedRooted<Value>newTarget(&rootValue1,REGS.sp[-1]);JSObject*obj=LambdaArrow(cx,fun,REGS.fp()->environmentChain(),newTarget);if(!obj)gotoerror;MOZ_ASSERT(obj->staticPrototype());REGS.sp[-1].setObject(*obj);}END_CASE(JSOP_LAMBDA_ARROW)CASE(JSOP_TOASYNC){ReservedRooted<JSFunction*>unwrapped(&rootFunction0,®S.sp[-1].toObject().as<JSFunction>());JSObject*wrapped=WrapAsyncFunction(cx,unwrapped);if(!wrapped)gotoerror;REGS.sp[-1].setObject(*wrapped);}END_CASE(JSOP_TOASYNC)CASE(JSOP_TOASYNCGEN){ReservedRooted<JSFunction*>unwrapped(&rootFunction0,®S.sp[-1].toObject().as<JSFunction>());JSObject*wrapped=WrapAsyncGenerator(cx,unwrapped);if(!wrapped)gotoerror;REGS.sp[-1].setObject(*wrapped);}END_CASE(JSOP_TOASYNCGEN)CASE(JSOP_TOASYNCITER){ReservedRooted<JSObject*>iter(&rootObject1,®S.sp[-1].toObject());JSObject*asyncIter=CreateAsyncFromSyncIterator(cx,iter);if(!asyncIter)gotoerror;REGS.sp[-1].setObject(*asyncIter);}END_CASE(JSOP_TOASYNCITER)CASE(JSOP_SETFUNNAME){MOZ_ASSERT(REGS.stackDepth()>=2);FunctionPrefixKindprefixKind=FunctionPrefixKind(GET_UINT8(REGS.pc));ReservedRooted<Value>name(&rootValue0,REGS.sp[-1]);ReservedRooted<JSFunction*>fun(&rootFunction0,®S.sp[-2].toObject().as<JSFunction>());if(!SetFunctionNameIfNoOwnName(cx,fun,name,prefixKind))gotoerror;REGS.sp--;}END_CASE(JSOP_SETFUNNAME)CASE(JSOP_CALLEE)MOZ_ASSERT(REGS.fp()->isFunctionFrame());PUSH_COPY(REGS.fp()->calleev());END_CASE(JSOP_CALLEE)CASE(JSOP_INITPROP_GETTER)CASE(JSOP_INITHIDDENPROP_GETTER)CASE(JSOP_INITPROP_SETTER)CASE(JSOP_INITHIDDENPROP_SETTER){MOZ_ASSERT(REGS.stackDepth()>=2);ReservedRooted<JSObject*>obj(&rootObject0,®S.sp[-2].toObject());ReservedRooted<PropertyName*>name(&rootName0,script->getName(REGS.pc));ReservedRooted<JSObject*>val(&rootObject1,®S.sp[-1].toObject());if(!InitGetterSetterOperation(cx,REGS.pc,obj,name,val))gotoerror;REGS.sp--;}END_CASE(JSOP_INITPROP_GETTER)CASE(JSOP_INITELEM_GETTER)CASE(JSOP_INITHIDDENELEM_GETTER)CASE(JSOP_INITELEM_SETTER)CASE(JSOP_INITHIDDENELEM_SETTER){MOZ_ASSERT(REGS.stackDepth()>=3);ReservedRooted<JSObject*>obj(&rootObject0,®S.sp[-3].toObject());ReservedRooted<Value>idval(&rootValue0,REGS.sp[-2]);ReservedRooted<JSObject*>val(&rootObject1,®S.sp[-1].toObject());if(!InitGetterSetterOperation(cx,REGS.pc,obj,idval,val))gotoerror;REGS.sp-=2;}END_CASE(JSOP_INITELEM_GETTER)CASE(JSOP_HOLE)PUSH_MAGIC(JS_ELEMENTS_HOLE);END_CASE(JSOP_HOLE)CASE(JSOP_NEWINIT){uint8_ti=GET_UINT8(REGS.pc);MOZ_ASSERT(i==JSProto_Array||i==JSProto_Object);JSObject*obj;if(i==JSProto_Array)obj=NewArrayOperation(cx,script,REGS.pc,0);elseobj=NewObjectOperation(cx,script,REGS.pc);if(!obj)gotoerror;PUSH_OBJECT(*obj);}END_CASE(JSOP_NEWINIT)CASE(JSOP_NEWARRAY)CASE(JSOP_SPREADCALLARRAY){uint32_tlength=GET_UINT32(REGS.pc);JSObject*obj=NewArrayOperation(cx,script,REGS.pc,length);if(!obj)gotoerror;PUSH_OBJECT(*obj);}END_CASE(JSOP_NEWARRAY)CASE(JSOP_NEWARRAY_COPYONWRITE){ReservedRooted<JSObject*>baseobj(&rootObject0,ObjectGroup::getOrFixupCopyOnWriteObject(cx,script,REGS.pc));if(!baseobj)gotoerror;ReservedRooted<JSObject*>obj(&rootObject1,NewDenseCopyOnWriteArray(cx,((RootedObject&)(baseobj)).as<ArrayObject>(),gc::DefaultHeap));if(!obj)gotoerror;PUSH_OBJECT(*obj);}END_CASE(JSOP_NEWARRAY_COPYONWRITE)CASE(JSOP_NEWOBJECT){JSObject*obj=NewObjectOperation(cx,script,REGS.pc);if(!obj)gotoerror;PUSH_OBJECT(*obj);}END_CASE(JSOP_NEWOBJECT)CASE(JSOP_MUTATEPROTO){MOZ_ASSERT(REGS.stackDepth()>=2);if(REGS.sp[-1].isObjectOrNull()){ReservedRooted<JSObject*>newProto(&rootObject1,REGS.sp[-1].toObjectOrNull());ReservedRooted<JSObject*>obj(&rootObject0,®S.sp[-2].toObject());MOZ_ASSERT(obj->is<PlainObject>());if(!SetPrototype(cx,obj,newProto))gotoerror;}REGS.sp--;}END_CASE(JSOP_MUTATEPROTO)CASE(JSOP_INITPROP)CASE(JSOP_INITLOCKEDPROP)CASE(JSOP_INITHIDDENPROP){static_assert(JSOP_INITPROP_LENGTH==JSOP_INITLOCKEDPROP_LENGTH,"initprop and initlockedprop must be the same size");static_assert(JSOP_INITPROP_LENGTH==JSOP_INITHIDDENPROP_LENGTH,"initprop and inithiddenprop must be the same size");/* Load the property's initial value into rval. */MOZ_ASSERT(REGS.stackDepth()>=2);ReservedRooted<Value>rval(&rootValue0,REGS.sp[-1]);/* Load the object being initialized into lval/obj. */ReservedRooted<JSObject*>obj(&rootObject0,®S.sp[-2].toObject());PropertyName*name=script->getName(REGS.pc);RootedId&id=rootId0;id=NameToId(name);if(!InitPropertyOperation(cx,JSOp(*REGS.pc),obj,id,rval))gotoerror;REGS.sp--;}END_CASE(JSOP_INITPROP)CASE(JSOP_INITELEM)CASE(JSOP_INITHIDDENELEM){MOZ_ASSERT(REGS.stackDepth()>=3);HandleValueval=REGS.stackHandleAt(-1);HandleValueid=REGS.stackHandleAt(-2);ReservedRooted<JSObject*>obj(&rootObject0,®S.sp[-3].toObject());if(!InitElemOperation(cx,REGS.pc,obj,id,val))gotoerror;REGS.sp-=2;}END_CASE(JSOP_INITELEM)CASE(JSOP_INITELEM_ARRAY){MOZ_ASSERT(REGS.stackDepth()>=2);HandleValueval=REGS.stackHandleAt(-1);ReservedRooted<JSObject*>obj(&rootObject0,®S.sp[-2].toObject());uint32_tindex=GET_UINT32(REGS.pc);if(!InitArrayElemOperation(cx,REGS.pc,obj,index,val))gotoerror;REGS.sp--;}END_CASE(JSOP_INITELEM_ARRAY)CASE(JSOP_INITELEM_INC){MOZ_ASSERT(REGS.stackDepth()>=3);HandleValueval=REGS.stackHandleAt(-1);ReservedRooted<JSObject*>obj(&rootObject0,®S.sp[-3].toObject());uint32_tindex=REGS.sp[-2].toInt32();if(!InitArrayElemOperation(cx,REGS.pc,obj,index,val))gotoerror;REGS.sp[-2].setInt32(index+1);REGS.sp--;}END_CASE(JSOP_INITELEM_INC)CASE(JSOP_GOSUB){PUSH_BOOLEAN(false);int32_ti=script->pcToOffset(REGS.pc)+JSOP_GOSUB_LENGTH;int32_tlen=GET_JUMP_OFFSET(REGS.pc);PUSH_INT32(i);ADVANCE_AND_DISPATCH(len);}CASE(JSOP_RETSUB){/* Pop [exception or hole, retsub pc-index]. */Valuerval,lval;POP_COPY_TO(rval);POP_COPY_TO(lval);MOZ_ASSERT(lval.isBoolean());if(lval.toBoolean()){/* * Exception was pending during finally, throw it *before* we adjust * pc, because pc indexes into script->trynotes. This turns out not to * be necessary, but it seems clearer. And it points out a FIXME: * 350509, due to Igor Bukanov. */cx->setPendingException(rval);gotoerror;}MOZ_ASSERT(rval.isInt32());/* Increment the PC by this much. */int32_tlen=rval.toInt32()-int32_t(script->pcToOffset(REGS.pc));ADVANCE_AND_DISPATCH(len);}CASE(JSOP_EXCEPTION){PUSH_NULL();MutableHandleValueres=REGS.stackHandleAt(-1);if(!GetAndClearException(cx,res))gotoerror;}END_CASE(JSOP_EXCEPTION)CASE(JSOP_FINALLY)CHECK_BRANCH();END_CASE(JSOP_FINALLY)CASE(JSOP_THROWING){ReservedRooted<Value>v(&rootValue0);POP_COPY_TO(v);MOZ_ALWAYS_TRUE(ThrowingOperation(cx,v));}END_CASE(JSOP_THROWING)CASE(JSOP_THROW){CHECK_BRANCH();ReservedRooted<Value>v(&rootValue0);POP_COPY_TO(v);JS_ALWAYS_FALSE(Throw(cx,v));/* let the code at error try to catch the exception. */gotoerror;}CASE(JSOP_INSTANCEOF){ReservedRooted<Value>rref(&rootValue0,REGS.sp[-1]);if(HandleValue(rref).isPrimitive()){ReportValueError(cx,JSMSG_BAD_INSTANCEOF_RHS,-1,rref,nullptr);gotoerror;}ReservedRooted<JSObject*>obj(&rootObject0,&rref.toObject());boolcond=false;if(!HasInstance(cx,obj,REGS.stackHandleAt(-2),&cond))gotoerror;REGS.sp--;REGS.sp[-1].setBoolean(cond);}END_CASE(JSOP_INSTANCEOF)CASE(JSOP_DEBUGGER){RootedValuerval(cx);switch(Debugger::onDebuggerStatement(cx,REGS.fp())){caseJSTRAP_ERROR:gotoerror;caseJSTRAP_CONTINUE:break;caseJSTRAP_RETURN:if(!ForcedReturn(cx,REGS))gotoerror;gotosuccessful_return_continuation;caseJSTRAP_THROW:gotoerror;default:;}}END_CASE(JSOP_DEBUGGER)CASE(JSOP_PUSHLEXICALENV){ReservedRooted<Scope*>scope(&rootScope0,script->getScope(REGS.pc));// Create block environment and push on scope chain.if(!REGS.fp()->pushLexicalEnvironment(cx,scope.as<LexicalScope>()))gotoerror;}END_CASE(JSOP_PUSHLEXICALENV)CASE(JSOP_POPLEXICALENV){#ifdef DEBUG// Pop block from scope chain.Scope*scope=script->lookupScope(REGS.pc);MOZ_ASSERT(scope);MOZ_ASSERT(scope->is<LexicalScope>());MOZ_ASSERT(scope->as<LexicalScope>().hasEnvironment());#endifif(MOZ_UNLIKELY(cx->compartment()->isDebuggee()))DebugEnvironments::onPopLexical(cx,REGS.fp(),REGS.pc);// Pop block from scope chain.REGS.fp()->popOffEnvironmentChain<LexicalEnvironmentObject>();}END_CASE(JSOP_POPLEXICALENV)CASE(JSOP_DEBUGLEAVELEXICALENV){MOZ_ASSERT(script->lookupScope(REGS.pc));MOZ_ASSERT(script->lookupScope(REGS.pc)->is<LexicalScope>());MOZ_ASSERT(!script->lookupScope(REGS.pc)->as<LexicalScope>().hasEnvironment());// FIXME: This opcode should not be necessary. The debugger shouldn't need// help from bytecode to do its job. See bug 927782.if(MOZ_UNLIKELY(cx->compartment()->isDebuggee()))DebugEnvironments::onPopLexical(cx,REGS.fp(),REGS.pc);}END_CASE(JSOP_DEBUGLEAVELEXICALENV)CASE(JSOP_FRESHENLEXICALENV){if(MOZ_UNLIKELY(cx->compartment()->isDebuggee()))DebugEnvironments::onPopLexical(cx,REGS.fp(),REGS.pc);if(!REGS.fp()->freshenLexicalEnvironment(cx))gotoerror;}END_CASE(JSOP_FRESHENLEXICALENV)CASE(JSOP_RECREATELEXICALENV){if(MOZ_UNLIKELY(cx->compartment()->isDebuggee()))DebugEnvironments::onPopLexical(cx,REGS.fp(),REGS.pc);if(!REGS.fp()->recreateLexicalEnvironment(cx))gotoerror;}END_CASE(JSOP_RECREATELEXICALENV)CASE(JSOP_PUSHVARENV){ReservedRooted<Scope*>scope(&rootScope0,script->getScope(REGS.pc));if(!REGS.fp()->pushVarEnvironment(cx,scope))gotoerror;}END_CASE(JSOP_PUSHVARENV)CASE(JSOP_POPVARENV){#ifdef DEBUGScope*scope=script->lookupScope(REGS.pc);MOZ_ASSERT(scope);MOZ_ASSERT(scope->is<VarScope>());MOZ_ASSERT(scope->as<VarScope>().hasEnvironment());#endifif(MOZ_UNLIKELY(cx->compartment()->isDebuggee()))DebugEnvironments::onPopVar(cx,REGS.fp(),REGS.pc);REGS.fp()->popOffEnvironmentChain<VarEnvironmentObject>();}END_CASE(JSOP_POPVARENV)CASE(JSOP_GENERATOR){MOZ_ASSERT(!cx->isExceptionPending());MOZ_ASSERT(REGS.stackDepth()==0);JSObject*obj=GeneratorObject::create(cx,REGS.fp());if(!obj)gotoerror;PUSH_OBJECT(*obj);}END_CASE(JSOP_GENERATOR)CASE(JSOP_INITIALYIELD){MOZ_ASSERT(!cx->isExceptionPending());MOZ_ASSERT(REGS.fp()->isFunctionFrame());ReservedRooted<JSObject*>obj(&rootObject0,®S.sp[-1].toObject());POP_RETURN_VALUE();MOZ_ASSERT(REGS.stackDepth()==0);if(!GeneratorObject::initialSuspend(cx,obj,REGS.fp(),REGS.pc))gotoerror;gotosuccessful_return_continuation;}CASE(JSOP_YIELD)CASE(JSOP_AWAIT){MOZ_ASSERT(!cx->isExceptionPending());MOZ_ASSERT(REGS.fp()->isFunctionFrame());ReservedRooted<JSObject*>obj(&rootObject0,®S.sp[-1].toObject());if(!GeneratorObject::normalSuspend(cx,obj,REGS.fp(),REGS.pc,REGS.spForStackDepth(0),REGS.stackDepth()-2)){gotoerror;}REGS.sp--;POP_RETURN_VALUE();gotosuccessful_return_continuation;}CASE(JSOP_RESUME){{ReservedRooted<JSObject*>gen(&rootObject0,®S.sp[-2].toObject());ReservedRooted<Value>val(&rootValue0,REGS.sp[-1]);// popInlineFrame expects there to be an additional value on the stack// to pop off, so leave "gen" on the stack.GeneratorObject::ResumeKindresumeKind=GeneratorObject::getResumeKind(REGS.pc);boolok=GeneratorObject::resume(cx,activation,gen,val,resumeKind);SET_SCRIPT(REGS.fp()->script());TraceLoggerThread*logger=TraceLoggerForCurrentThread(cx);TraceLoggerEventscriptEvent(TraceLogger_Scripts,script);TraceLogStartEvent(logger,scriptEvent);TraceLogStartEvent(logger,TraceLogger_Interpreter);if(!ok)gotoerror;}ADVANCE_AND_DISPATCH(0);}CASE(JSOP_DEBUGAFTERYIELD){// No-op in the interpreter, as GeneratorObject::resume takes care of// fixing up InterpreterFrames.MOZ_ASSERT_IF(REGS.fp()->script()->isDebuggee(),REGS.fp()->isDebuggee());}END_CASE(JSOP_DEBUGAFTERYIELD)CASE(JSOP_FINALYIELDRVAL){ReservedRooted<JSObject*>gen(&rootObject0,®S.sp[-1].toObject());REGS.sp--;if(!GeneratorObject::finalSuspend(cx,gen)){interpReturnOK=false;gotoreturn_continuation;}gotosuccessful_return_continuation;}CASE(JSOP_ARRAYPUSH){ReservedRooted<JSObject*>obj(&rootObject0,®S.sp[-1].toObject());if(!NewbornArrayPush(cx,obj,REGS.sp[-2]))gotoerror;REGS.sp-=2;}END_CASE(JSOP_ARRAYPUSH)CASE(JSOP_CHECKCLASSHERITAGE){HandleValueheritage=REGS.stackHandleAt(-1);if(!CheckClassHeritageOperation(cx,heritage))gotoerror;}END_CASE(JSOP_CHECKCLASSHERITAGE)CASE(JSOP_BUILTINPROTO){ReservedRooted<JSObject*>builtin(&rootObject0);MOZ_ASSERT(GET_UINT8(REGS.pc)<JSProto_LIMIT);JSProtoKeykey=static_cast<JSProtoKey>(GET_UINT8(REGS.pc));if(!GetBuiltinPrototype(cx,key,&builtin))gotoerror;PUSH_OBJECT(*builtin);}END_CASE(JSOP_BUILTINPROTO)CASE(JSOP_FUNWITHPROTO){ReservedRooted<JSObject*>proto(&rootObject1,®S.sp[-1].toObject());/* Load the specified function object literal. */ReservedRooted<JSFunction*>fun(&rootFunction0,script->getFunction(GET_UINT32_INDEX(REGS.pc)));JSObject*obj=FunWithProtoOperation(cx,fun,REGS.fp()->environmentChain(),proto);if(!obj)gotoerror;REGS.sp[-1].setObject(*obj);}END_CASE(JSOP_FUNWITHPROTO)CASE(JSOP_OBJWITHPROTO){JSObject*obj=ObjectWithProtoOperation(cx,REGS.stackHandleAt(-1));if(!obj)gotoerror;REGS.sp[-1].setObject(*obj);}END_CASE(JSOP_OBJWITHPROTO)CASE(JSOP_INITHOMEOBJECT){unsignedskipOver=GET_UINT8(REGS.pc);MOZ_ASSERT(REGS.stackDepth()>=skipOver+2);/* Load the function to be initialized */ReservedRooted<JSFunction*>func(&rootFunction0,®S.sp[-1].toObject().as<JSFunction>());MOZ_ASSERT(func->allowSuperProperty());/* Load the home object */ReservedRooted<JSObject*>obj(&rootObject0);obj=®S.sp[int(-2-skipOver)].toObject();MOZ_ASSERT(obj->is<PlainObject>()||obj->is<UnboxedPlainObject>()||obj->is<JSFunction>());func->setExtendedSlot(FunctionExtended::METHOD_HOMEOBJECT_SLOT,ObjectValue(*obj));}END_CASE(JSOP_INITHOMEOBJECT)CASE(JSOP_SUPERBASE){JSFunction&superEnvFunc=GetSuperEnvFunction(cx,REGS);MOZ_ASSERT(superEnvFunc.allowSuperProperty());MOZ_ASSERT(superEnvFunc.nonLazyScript()->needsHomeObject());constValue&homeObjVal=superEnvFunc.getExtendedSlot(FunctionExtended::METHOD_HOMEOBJECT_SLOT);ReservedRooted<JSObject*>homeObj(&rootObject0,&homeObjVal.toObject());ReservedRooted<JSObject*>superBase(&rootObject1);superBase=HomeObjectSuperBase(cx,homeObj);if(!superBase)gotoerror;PUSH_OBJECT(*superBase);}END_CASE(JSOP_SUPERBASE)CASE(JSOP_NEWTARGET)PUSH_COPY(REGS.fp()->newTarget());MOZ_ASSERT(REGS.sp[-1].isObject()||REGS.sp[-1].isUndefined());END_CASE(JSOP_NEWTARGET)CASE(JSOP_SUPERFUN){ReservedRooted<JSObject*>superEnvFunc(&rootObject0,&GetSuperEnvFunction(cx,REGS));ReservedRooted<JSObject*>superFun(&rootObject1);superFun=SuperFunOperation(cx,superEnvFunc);if(!superFun)gotoerror;PUSH_OBJECT(*superFun);}END_CASE(JSOP_SUPERFUN)CASE(JSOP_DERIVEDCONSTRUCTOR){MOZ_ASSERT(REGS.sp[-1].isObject());ReservedRooted<JSObject*>proto(&rootObject0,®S.sp[-1].toObject());JSFunction*constructor=MakeDefaultConstructor(cx,script,REGS.pc,proto);if(!constructor)gotoerror;REGS.sp[-1].setObject(*constructor);}END_CASE(JSOP_DERIVEDCONSTRUCTOR)CASE(JSOP_CLASSCONSTRUCTOR){JSFunction*constructor=MakeDefaultConstructor(cx,script,REGS.pc,nullptr);if(!constructor)gotoerror;PUSH_OBJECT(*constructor);}END_CASE(JSOP_CLASSCONSTRUCTOR)CASE(JSOP_CHECKOBJCOERCIBLE){ReservedRooted<Value>checkVal(&rootValue0,REGS.sp[-1]);if(checkVal.isNullOrUndefined()&&!ToObjectFromStack(cx,checkVal))gotoerror;}END_CASE(JSOP_CHECKOBJCOERCIBLE)CASE(JSOP_DEBUGCHECKSELFHOSTED){#ifdef DEBUGReservedRooted<Value>checkVal(&rootValue0,REGS.sp[-1]);if(!Debug_CheckSelfHosted(cx,checkVal))gotoerror;#endif}END_CASE(JSOP_DEBUGCHECKSELFHOSTED)CASE(JSOP_IS_CONSTRUCTING)PUSH_MAGIC(JS_IS_CONSTRUCTING);END_CASE(JSOP_IS_CONSTRUCTING)DEFAULT(){charnumBuf[12];SprintfLiteral(numBuf,"%d",*REGS.pc);JS_ReportErrorNumberASCII(cx,GetErrorMessage,nullptr,JSMSG_BAD_BYTECODE,numBuf);gotoerror;}}/* interpreter loop */MOZ_CRASH("Interpreter loop exited via fallthrough");error:switch(HandleError(cx,REGS)){caseSuccessfulReturnContinuation:gotosuccessful_return_continuation;caseErrorReturnContinuation:interpReturnOK=false;gotoreturn_continuation;caseCatchContinuation:ADVANCE_AND_DISPATCH(0);caseFinallyContinuation:{/* * Push (true, exception) pair for finally to indicate that [retsub] * should rethrow the exception. */ReservedRooted<Value>exception(&rootValue0);if(!cx->getPendingException(&exception)){interpReturnOK=false;gotoreturn_continuation;}PUSH_BOOLEAN(true);PUSH_COPY(exception);cx->clearPendingException();}ADVANCE_AND_DISPATCH(0);}MOZ_CRASH("Invalid HandleError continuation");exit:if(MOZ_LIKELY(!frameHalfInitialized)){interpReturnOK=Debugger::onLeaveFrame(cx,REGS.fp(),REGS.pc,interpReturnOK);REGS.fp()->epilogue(cx,REGS.pc);}gc::MaybeVerifyBarriers(cx,true);TraceLogStopEvent(logger,TraceLogger_Engine);TraceLogStopEvent(logger,scriptEvent);/* * This path is used when it's guaranteed the method can be finished * inside the JIT. */leave_on_safe_point:if(interpReturnOK)state.setReturnValue(activation.entryFrame()->returnValue());returninterpReturnOK;prologue_error:interpReturnOK=false;frameHalfInitialized=true;gotoprologue_return_continuation;}booljs::Throw(JSContext*cx,HandleValuev){MOZ_ASSERT(!cx->isExceptionPending());cx->setPendingException(v);returnfalse;}booljs::ThrowingOperation(JSContext*cx,HandleValuev){// Like js::Throw, but returns |true| instead of |false| to continue// execution instead of calling the (JIT) exception handler.MOZ_ASSERT(!cx->isExceptionPending());cx->setPendingException(v);returntrue;}booljs::GetProperty(JSContext*cx,HandleValuev,HandlePropertyNamename,MutableHandleValuevp){if(name==cx->names().length){// Fast path for strings, arrays and arguments.if(GetLengthProperty(v,vp))returntrue;}// Optimize common cases like (2).toString() or "foo".valueOf() to not// create a wrapper object.if(v.isPrimitive()&&!v.isNullOrUndefined()){NativeObject*proto;if(v.isNumber()){proto=GlobalObject::getOrCreateNumberPrototype(cx,cx->global());}elseif(v.isString()){proto=GlobalObject::getOrCreateStringPrototype(cx,cx->global());}elseif(v.isBoolean()){proto=GlobalObject::getOrCreateBooleanPrototype(cx,cx->global());}else{MOZ_ASSERT(v.isSymbol());proto=GlobalObject::getOrCreateSymbolPrototype(cx,cx->global());}if(!proto)returnfalse;if(GetPropertyPure(cx,proto,NameToId(name),vp.address()))returntrue;}RootedValuereceiver(cx,v);RootedObjectobj(cx,ToObjectFromStack(cx,v));if(!obj)returnfalse;returnGetProperty(cx,obj,receiver,name,vp);}JSObject*js::Lambda(JSContext*cx,HandleFunctionfun,HandleObjectparent){MOZ_ASSERT(!fun->isArrow());RootedObjectclone(cx,CloneFunctionObjectIfNotSingleton(cx,fun,parent));if(!clone)returnnullptr;MOZ_ASSERT(fun->global()==clone->global());returnclone;}JSObject*js::LambdaArrow(JSContext*cx,HandleFunctionfun,HandleObjectparent,HandleValuenewTargetv){MOZ_ASSERT(fun->isArrow());RootedObjectclone(cx,CloneFunctionObjectIfNotSingleton(cx,fun,parent,nullptr,TenuredObject));if(!clone)returnnullptr;MOZ_ASSERT(clone->as<JSFunction>().isArrow());clone->as<JSFunction>().setExtendedSlot(0,newTargetv);MOZ_ASSERT(fun->global()==clone->global());returnclone;}booljs::DefFunOperation(JSContext*cx,HandleScriptscript,HandleObjectenvChain,HandleFunctionfun){/* * We define the function as a property of the variable object and not the * current scope chain even for the case of function expression statements * and functions defined by eval inside let or with blocks. */RootedObjectparent(cx,envChain);while(!parent->isQualifiedVarObj())parent=parent->enclosingEnvironment();/* ES5 10.5 (NB: with subsequent errata). */RootedPropertyNamename(cx,fun->explicitName()->asPropertyName());Rooted<PropertyResult>prop(cx);RootedObjectpobj(cx);if(!LookupProperty(cx,parent,name,&pobj,&prop))returnfalse;RootedValuerval(cx,ObjectValue(*fun));/* * ECMA requires functions defined when entering Eval code to be * impermanent. */unsignedattrs=script->isActiveEval()?JSPROP_ENUMERATE:JSPROP_ENUMERATE|JSPROP_PERMANENT;/* Steps 5d, 5f. */if(!prop||pobj!=parent){if(!DefineProperty(cx,parent,name,rval,nullptr,nullptr,attrs))returnfalse;returnparent->is<GlobalObject>()?parent->compartment()->addToVarNames(cx,name):true;}/* * Step 5e. * * A DebugEnvironmentProxy is okay here, and sometimes necessary. If * Debugger.Frame.prototype.eval defines a function with the same name as an * extant variable in the frame, the DebugEnvironmentProxy takes care of storing * the function in the stack frame (for non-aliased variables) or on the * scope object (for aliased). */MOZ_ASSERT(parent->isNative()||parent->is<DebugEnvironmentProxy>());if(parent->is<GlobalObject>()){Shape*shape=prop.shape();if(shape->configurable()){if(!DefineProperty(cx,parent,name,rval,nullptr,nullptr,attrs))returnfalse;}else{MOZ_ASSERT(shape->isDataDescriptor());MOZ_ASSERT(shape->writable());MOZ_ASSERT(shape->enumerable());}// Careful: the presence of a shape, even one appearing to derive from// a variable declaration, doesn't mean it's in [[VarNames]].if(!parent->compartment()->addToVarNames(cx,name))returnfalse;}/* * Non-global properties, and global properties which we aren't simply * redefining, must be set. First, this preserves their attributes. * Second, this will produce warnings and/or errors as necessary if the * specified Call object property is not writable (const). *//* Step 5f. */RootedIdid(cx,NameToId(name));returnPutProperty(cx,parent,id,rval,script->strict());}booljs::ThrowMsgOperation(JSContext*cx,constunsignederrorNum){JS_ReportErrorNumberASCII(cx,GetErrorMessage,nullptr,errorNum);returnfalse;}booljs::GetAndClearException(JSContext*cx,MutableHandleValueres){if(!cx->getPendingException(res))returnfalse;cx->clearPendingException();// Allow interrupting deeply nested exception handling.returnCheckForInterrupt(cx);}template<boolstrict>booljs::DeletePropertyJit(JSContext*cx,HandleValuev,HandlePropertyNamename,bool*bp){RootedObjectobj(cx,ToObjectFromStack(cx,v));if(!obj)returnfalse;RootedIdid(cx,NameToId(name));ObjectOpResultresult;if(!DeleteProperty(cx,obj,id,result))returnfalse;if(strict){if(!result)returnresult.reportError(cx,obj,id);*bp=true;}else{*bp=result.ok();}returntrue;}templatebooljs::DeletePropertyJit<true>(JSContext*cx,HandleValueval,HandlePropertyNamename,bool*bp);templatebooljs::DeletePropertyJit<false>(JSContext*cx,HandleValueval,HandlePropertyNamename,bool*bp);template<boolstrict>booljs::DeleteElementJit(JSContext*cx,HandleValueval,HandleValueindex,bool*bp){RootedObjectobj(cx,ToObjectFromStack(cx,val));if(!obj)returnfalse;RootedIdid(cx);if(!ToPropertyKey(cx,index,&id))returnfalse;ObjectOpResultresult;if(!DeleteProperty(cx,obj,id,result))returnfalse;if(strict){if(!result)returnresult.reportError(cx,obj,id);*bp=true;}else{*bp=result.ok();}returntrue;}templatebooljs::DeleteElementJit<true>(JSContext*,HandleValue,HandleValue,bool*succeeded);templatebooljs::DeleteElementJit<false>(JSContext*,HandleValue,HandleValue,bool*succeeded);booljs::GetElement(JSContext*cx,MutableHandleValuelref,HandleValuerref,MutableHandleValuevp){returnGetElementOperation(cx,JSOP_GETELEM,lref,rref,vp);}booljs::CallElement(JSContext*cx,MutableHandleValuelref,HandleValuerref,MutableHandleValueres){returnGetElementOperation(cx,JSOP_CALLELEM,lref,rref,res);}booljs::SetObjectElement(JSContext*cx,HandleObjectobj,HandleValueindex,HandleValuevalue,boolstrict){RootedIdid(cx);if(!ToPropertyKey(cx,index,&id))returnfalse;RootedValuereceiver(cx,ObjectValue(*obj));returnSetObjectElementOperation(cx,obj,id,value,receiver,strict);}booljs::SetObjectElement(JSContext*cx,HandleObjectobj,HandleValueindex,HandleValuevalue,boolstrict,HandleScriptscript,jsbytecode*pc){MOZ_ASSERT(pc);RootedIdid(cx);if(!ToPropertyKey(cx,index,&id))returnfalse;RootedValuereceiver(cx,ObjectValue(*obj));returnSetObjectElementOperation(cx,obj,id,value,receiver,strict,script,pc);}booljs::SetObjectElement(JSContext*cx,HandleObjectobj,HandleValueindex,HandleValuevalue,HandleValuereceiver,boolstrict){RootedIdid(cx);if(!ToPropertyKey(cx,index,&id))returnfalse;returnSetObjectElementOperation(cx,obj,id,value,receiver,strict);}booljs::SetObjectElement(JSContext*cx,HandleObjectobj,HandleValueindex,HandleValuevalue,HandleValuereceiver,boolstrict,HandleScriptscript,jsbytecode*pc){MOZ_ASSERT(pc);RootedIdid(cx);if(!ToPropertyKey(cx,index,&id))returnfalse;returnSetObjectElementOperation(cx,obj,id,value,receiver,strict,script,pc);}booljs::InitElementArray(JSContext*cx,jsbytecode*pc,HandleObjectobj,uint32_tindex,HandleValuevalue){returnInitArrayElemOperation(cx,pc,obj,index,value);}booljs::AddValues(JSContext*cx,MutableHandleValuelhs,MutableHandleValuerhs,MutableHandleValueres){returnAddOperation(cx,lhs,rhs,res);}booljs::SubValues(JSContext*cx,MutableHandleValuelhs,MutableHandleValuerhs,MutableHandleValueres){returnSubOperation(cx,lhs,rhs,res);}booljs::MulValues(JSContext*cx,MutableHandleValuelhs,MutableHandleValuerhs,MutableHandleValueres){returnMulOperation(cx,lhs,rhs,res);}booljs::DivValues(JSContext*cx,MutableHandleValuelhs,MutableHandleValuerhs,MutableHandleValueres){returnDivOperation(cx,lhs,rhs,res);}booljs::ModValues(JSContext*cx,MutableHandleValuelhs,MutableHandleValuerhs,MutableHandleValueres){returnModOperation(cx,lhs,rhs,res);}booljs::UrshValues(JSContext*cx,MutableHandleValuelhs,MutableHandleValuerhs,MutableHandleValueres){returnUrshOperation(cx,lhs,rhs,res);}booljs::AtomicIsLockFree(JSContext*cx,HandleValuein,int*out){inti;if(!ToInt32(cx,in,&i))returnfalse;*out=js::jit::AtomicOperations::isLockfree(i);returntrue;}booljs::DeleteNameOperation(JSContext*cx,HandlePropertyNamename,HandleObjectscopeObj,MutableHandleValueres){RootedObjectscope(cx),pobj(cx);Rooted<PropertyResult>prop(cx);if(!LookupName(cx,name,scopeObj,&scope,&pobj,&prop))returnfalse;if(!scope){// Return true for non-existent names.res.setBoolean(true);returntrue;}ObjectOpResultresult;RootedIdid(cx,NameToId(name));if(!DeleteProperty(cx,scope,id,result))returnfalse;boolstatus=result.ok();res.setBoolean(status);if(status){// Deleting a name from the global object removes it from [[VarNames]].if(pobj==scope&&scope->is<GlobalObject>())scope->compartment()->removeFromVarNames(name);}returntrue;}booljs::ImplicitThisOperation(JSContext*cx,HandleObjectscopeObj,HandlePropertyNamename,MutableHandleValueres){RootedObjectobj(cx);if(!LookupNameWithGlobalDefault(cx,name,scopeObj,&obj))returnfalse;res.set(ComputeImplicitThis(obj));returntrue;}booljs::RunOnceScriptPrologue(JSContext*cx,HandleScriptscript){MOZ_ASSERT(script->treatAsRunOnce());if(!script->hasRunOnce()){script->setHasRunOnce();returntrue;}// Force instantiation of the script's function's group to ensure the flag// is preserved in type information.RootedFunctionfun(cx,script->functionNonDelazifying());if(!JSObject::getGroup(cx,fun))returnfalse;MarkObjectGroupFlags(cx,script->functionNonDelazifying(),OBJECT_FLAG_RUNONCE_INVALIDATED);returntrue;}unsignedjs::GetInitDataPropAttrs(JSOpop){switch(op){caseJSOP_INITPROP:returnJSPROP_ENUMERATE;caseJSOP_INITLOCKEDPROP:returnJSPROP_PERMANENT|JSPROP_READONLY;caseJSOP_INITHIDDENPROP:// Non-enumerable, but writable and configurablereturn0;default:;}MOZ_CRASH("Unknown data initprop");}booljs::InitGetterSetterOperation(JSContext*cx,jsbytecode*pc,HandleObjectobj,HandleIdid,HandleObjectval){MOZ_ASSERT(val->isCallable());GetterOpgetter;SetterOpsetter;unsignedattrs=JSPROP_SHARED;JSOpop=JSOp(*pc);if(!IsHiddenInitOp(op))attrs|=JSPROP_ENUMERATE;if(op==JSOP_INITPROP_GETTER||op==JSOP_INITELEM_GETTER||op==JSOP_INITHIDDENPROP_GETTER||op==JSOP_INITHIDDENELEM_GETTER){getter=CastAsGetterOp(val);setter=nullptr;attrs|=JSPROP_GETTER;}else{MOZ_ASSERT(op==JSOP_INITPROP_SETTER||op==JSOP_INITELEM_SETTER||op==JSOP_INITHIDDENPROP_SETTER||op==JSOP_INITHIDDENELEM_SETTER);getter=nullptr;setter=CastAsSetterOp(val);attrs|=JSPROP_SETTER;}RootedValuescratch(cx);returnDefineProperty(cx,obj,id,scratch,getter,setter,attrs);}booljs::InitGetterSetterOperation(JSContext*cx,jsbytecode*pc,HandleObjectobj,HandlePropertyNamename,HandleObjectval){RootedIdid(cx,NameToId(name));returnInitGetterSetterOperation(cx,pc,obj,id,val);}booljs::InitGetterSetterOperation(JSContext*cx,jsbytecode*pc,HandleObjectobj,HandleValueidval,HandleObjectval){RootedIdid(cx);if(!ToPropertyKey(cx,idval,&id))returnfalse;returnInitGetterSetterOperation(cx,pc,obj,id,val);}booljs::SpreadCallOperation(JSContext*cx,HandleScriptscript,jsbytecode*pc,HandleValuethisv,HandleValuecallee,HandleValuearr,HandleValuenewTarget,MutableHandleValueres){RootedArrayObjectaobj(cx,&arr.toObject().as<ArrayObject>());uint32_tlength=aobj->length();JSOpop=JSOp(*pc);boolconstructing=op==JSOP_SPREADNEW||op==JSOP_SPREADSUPERCALL;// {Construct,Invoke}Args::init does this too, but this gives us a better// error message.if(length>ARGS_LENGTH_MAX){JS_ReportErrorNumberASCII(cx,GetErrorMessage,nullptr,constructing?JSMSG_TOO_MANY_CON_SPREADARGS:JSMSG_TOO_MANY_FUN_SPREADARGS);returnfalse;}// Do our own checks for the callee being a function, as Invoke uses the// expression decompiler to decompile the callee stack operand based on// the number of arguments. Spread operations have the callee at sp - 3// when not constructing, and sp - 4 when constructing.if(callee.isPrimitive()){returnReportIsNotFunction(cx,callee,2+constructing,constructing?CONSTRUCT:NO_CONSTRUCT);}if(MOZ_UNLIKELY(!callee.toObject().is<JSFunction>())&&!callee.toObject().callHook()){returnReportIsNotFunction(cx,callee,2+constructing,constructing?CONSTRUCT:NO_CONSTRUCT);}#ifdef DEBUG// The object must be an array with dense elements and no holes. Baseline's// optimized spread call stubs rely on this.MOZ_ASSERT(!aobj->isIndexed());MOZ_ASSERT(aobj->getDenseInitializedLength()==aobj->length());for(size_ti=0;i<aobj->length();i++)MOZ_ASSERT(!aobj->getDenseElement(i).isMagic(JS_ELEMENTS_HOLE));#endifif(constructing){if(!StackCheckIsConstructorCalleeNewTarget(cx,callee,newTarget))returnfalse;ConstructArgscargs(cx);if(!cargs.init(cx,length))returnfalse;if(!GetElements(cx,aobj,length,cargs.array()))returnfalse;RootedObjectobj(cx);if(!Construct(cx,callee,cargs,newTarget,&obj))returnfalse;res.setObject(*obj);}else{InvokeArgsargs(cx);if(!args.init(cx,length))returnfalse;if(!GetElements(cx,aobj,length,args.array()))returnfalse;if((op==JSOP_SPREADEVAL||op==JSOP_STRICTSPREADEVAL)&&cx->global()->valueIsEval(callee)){if(!DirectEval(cx,args.get(0),res))returnfalse;}else{MOZ_ASSERT(op==JSOP_SPREADCALL||op==JSOP_SPREADEVAL||op==JSOP_STRICTSPREADEVAL,"bad spread opcode");if(!Call(cx,callee,thisv,args,res))returnfalse;}}TypeScript::Monitor(cx,script,pc,res);returntrue;}booljs::OptimizeSpreadCall(JSContext*cx,HandleValuearg,bool*optimized){// Optimize spread call by skipping spread operation when following// conditions are met:// * the argument is an array// * the array has no hole// * array[@@iterator] is not modified// * the array's prototype is Array.prototype// * Array.prototype[@@iterator] is not modified// * %ArrayIteratorPrototype%.next is not modifiedif(!arg.isObject()){*optimized=false;returntrue;}RootedObjectobj(cx,&arg.toObject());if(!IsPackedArray(obj)){*optimized=false;returntrue;}ForOfPIC::Chain*stubChain=ForOfPIC::getOrCreate(cx);if(!stubChain)returnfalse;returnstubChain->tryOptimizeArray(cx,obj.as<ArrayObject>(),optimized);}JSObject*js::NewObjectOperation(JSContext*cx,HandleScriptscript,jsbytecode*pc,NewObjectKindnewKind/* = GenericObject */){MOZ_ASSERT(newKind!=SingletonObject);RootedObjectGroupgroup(cx);if(ObjectGroup::useSingletonForAllocationSite(script,pc,JSProto_Object)){newKind=SingletonObject;}else{group=ObjectGroup::allocationSiteGroup(cx,script,pc,JSProto_Object);if(!group)returnnullptr;if(group->maybePreliminaryObjects()){group->maybePreliminaryObjects()->maybeAnalyze(cx,group);if(group->maybeUnboxedLayout())group->maybeUnboxedLayout()->setAllocationSite(script,pc);}if(group->shouldPreTenure()||group->maybePreliminaryObjects())newKind=TenuredObject;if(group->maybeUnboxedLayout())returnUnboxedPlainObject::create(cx,group,newKind);}RootedObjectobj(cx);if(*pc==JSOP_NEWOBJECT){RootedPlainObjectbaseObject(cx,&script->getObject(pc)->as<PlainObject>());obj=CopyInitializerObject(cx,baseObject,newKind);}else{MOZ_ASSERT(*pc==JSOP_NEWINIT);MOZ_ASSERT(GET_UINT8(pc)==JSProto_Object);obj=NewBuiltinClassInstance<PlainObject>(cx,newKind);}if(!obj)returnnullptr;if(newKind==SingletonObject){if(!JSObject::setSingleton(cx,obj))returnnullptr;}else{obj->setGroup(group);if(PreliminaryObjectArray*preliminaryObjects=group->maybePreliminaryObjects())preliminaryObjects->registerNewObject(obj);}returnobj;}JSObject*js::NewObjectOperationWithTemplate(JSContext*cx,HandleObjecttemplateObject){// This is an optimized version of NewObjectOperation for use when the// object is not a singleton and has had its preliminary objects analyzed,// with the template object a copy of the object to create.MOZ_ASSERT(!templateObject->isSingleton());NewObjectKindnewKind=templateObject->group()->shouldPreTenure()?TenuredObject:GenericObject;if(templateObject->group()->maybeUnboxedLayout()){RootedObjectGroupgroup(cx,templateObject->group());returnUnboxedPlainObject::create(cx,group,newKind);}JSObject*obj=CopyInitializerObject(cx,templateObject.as<PlainObject>(),newKind);if(!obj)returnnullptr;obj->setGroup(templateObject->group());returnobj;}JSObject*js::NewArrayOperation(JSContext*cx,HandleScriptscript,jsbytecode*pc,uint32_tlength,NewObjectKindnewKind/* = GenericObject */){MOZ_ASSERT(newKind!=SingletonObject);RootedObjectGroupgroup(cx);if(ObjectGroup::useSingletonForAllocationSite(script,pc,JSProto_Array)){newKind=SingletonObject;}else{group=ObjectGroup::allocationSiteGroup(cx,script,pc,JSProto_Array);if(!group)returnnullptr;if(group->maybePreliminaryObjects())group->maybePreliminaryObjects()->maybeAnalyze(cx,group);if(group->shouldPreTenure()||group->maybePreliminaryObjects())newKind=TenuredObject;if(group->maybeUnboxedLayout())returnUnboxedArrayObject::create(cx,group,length,newKind);}ArrayObject*obj=NewDenseFullyAllocatedArray(cx,length,nullptr,newKind);if(!obj)returnnullptr;if(newKind==SingletonObject){MOZ_ASSERT(obj->isSingleton());}else{obj->setGroup(group);if(PreliminaryObjectArray*preliminaryObjects=group->maybePreliminaryObjects())preliminaryObjects->registerNewObject(obj);}returnobj;}JSObject*js::NewArrayOperationWithTemplate(JSContext*cx,HandleObjecttemplateObject){MOZ_ASSERT(!templateObject->isSingleton());NewObjectKindnewKind=templateObject->group()->shouldPreTenure()?TenuredObject:GenericObject;if(templateObject->is<UnboxedArrayObject>()){uint32_tlength=templateObject->as<UnboxedArrayObject>().length();RootedObjectGroupgroup(cx,templateObject->group());returnUnboxedArrayObject::create(cx,group,length,newKind);}ArrayObject*obj=NewDenseFullyAllocatedArray(cx,templateObject->as<ArrayObject>().length(),nullptr,newKind);if(!obj)returnnullptr;MOZ_ASSERT(obj->lastProperty()==templateObject->as<ArrayObject>().lastProperty());obj->setGroup(templateObject->group());returnobj;}voidjs::ReportRuntimeLexicalError(JSContext*cx,unsignederrorNumber,HandleIdid){MOZ_ASSERT(errorNumber==JSMSG_UNINITIALIZED_LEXICAL||errorNumber==JSMSG_BAD_CONST_ASSIGN);JSAutoByteStringprintable;if(ValueToPrintable(cx,IdToValue(id),&printable))JS_ReportErrorNumberLatin1(cx,GetErrorMessage,nullptr,errorNumber,printable.ptr());}voidjs::ReportRuntimeLexicalError(JSContext*cx,unsignederrorNumber,HandlePropertyNamename){RootedIdid(cx,NameToId(name));ReportRuntimeLexicalError(cx,errorNumber,id);}voidjs::ReportRuntimeLexicalError(JSContext*cx,unsignederrorNumber,HandleScriptscript,jsbytecode*pc){JSOpop=JSOp(*pc);MOZ_ASSERT(op==JSOP_CHECKLEXICAL||op==JSOP_CHECKALIASEDLEXICAL||op==JSOP_THROWSETCONST||op==JSOP_THROWSETALIASEDCONST||op==JSOP_THROWSETCALLEE||op==JSOP_GETIMPORT);RootedPropertyNamename(cx);if(op==JSOP_THROWSETCALLEE){name=script->functionNonDelazifying()->explicitName()->asPropertyName();}elseif(IsLocalOp(op)){name=FrameSlotName(script,pc)->asPropertyName();}elseif(IsAtomOp(op)){name=script->getName(pc);}else{MOZ_ASSERT(IsAliasedVarOp(op));name=EnvironmentCoordinateName(cx->caches().envCoordinateNameCache,script,pc);}ReportRuntimeLexicalError(cx,errorNumber,name);}voidjs::ReportRuntimeRedeclaration(JSContext*cx,HandlePropertyNamename,constchar*redeclKind){JSAutoByteStringprintable;if(AtomToPrintableString(cx,name,&printable)){JS_ReportErrorNumberLatin1(cx,GetErrorMessage,nullptr,JSMSG_REDECLARED_VAR,redeclKind,printable.ptr());}}booljs::ThrowCheckIsObject(JSContext*cx,CheckIsObjectKindkind){switch(kind){caseCheckIsObjectKind::IteratorNext:JS_ReportErrorNumberASCII(cx,GetErrorMessage,nullptr,JSMSG_ITER_METHOD_RETURNED_PRIMITIVE,"next");break;caseCheckIsObjectKind::IteratorReturn:JS_ReportErrorNumberASCII(cx,GetErrorMessage,nullptr,JSMSG_ITER_METHOD_RETURNED_PRIMITIVE,"return");break;caseCheckIsObjectKind::IteratorThrow:JS_ReportErrorNumberASCII(cx,GetErrorMessage,nullptr,JSMSG_ITER_METHOD_RETURNED_PRIMITIVE,"throw");break;caseCheckIsObjectKind::GetIterator:JS_ReportErrorNumberASCII(cx,GetErrorMessage,nullptr,JSMSG_GET_ITER_RETURNED_PRIMITIVE);break;caseCheckIsObjectKind::GetAsyncIterator:JS_ReportErrorNumberASCII(cx,GetErrorMessage,nullptr,JSMSG_GET_ASYNC_ITER_RETURNED_PRIMITIVE);break;default:MOZ_CRASH("Unknown kind");}returnfalse;}booljs::ThrowCheckIsCallable(JSContext*cx,CheckIsCallableKindkind){switch(kind){caseCheckIsCallableKind::IteratorReturn:JS_ReportErrorNumberASCII(cx,GetErrorMessage,nullptr,JSMSG_RETURN_NOT_CALLABLE);break;default:MOZ_CRASH("Unknown kind");}returnfalse;}booljs::ThrowUninitializedThis(JSContext*cx,AbstractFramePtrframe){RootedFunctionfun(cx);if(frame.isFunctionFrame()){fun=frame.callee();}else{Scope*startingScope;if(frame.isDebuggerEvalFrame()){AbstractFramePtrevalInFramePrev=frame.asInterpreterFrame()->evalInFramePrev();startingScope=evalInFramePrev.script()->bodyScope();}else{MOZ_ASSERT(frame.isEvalFrame());MOZ_ASSERT(frame.script()->isDirectEvalInFunction());startingScope=frame.script()->enclosingScope();}for(ScopeItersi(startingScope);si;si++){if(si.scope()->is<FunctionScope>()){fun=si.scope()->as<FunctionScope>().canonicalFunction();break;}}MOZ_ASSERT(fun);}if(fun->isDerivedClassConstructor()){constchar*name="anonymous";JSAutoByteStringstr;if(fun->explicitName()){if(!AtomToPrintableString(cx,fun->explicitName(),&str))returnfalse;name=str.ptr();}JS_ReportErrorNumberLatin1(cx,GetErrorMessage,nullptr,JSMSG_UNINITIALIZED_THIS,name);returnfalse;}MOZ_ASSERT(fun->isArrow());JS_ReportErrorNumberUTF8(cx,GetErrorMessage,nullptr,JSMSG_UNINITIALIZED_THIS_ARROW);returnfalse;}JSObject*js::HomeObjectSuperBase(JSContext*cx,HandleObjecthomeObj){RootedObjectsuperBase(cx);if(!GetPrototype(cx,homeObj,&superBase))returnnullptr;if(!superBase){JS_ReportErrorNumberASCII(cx,GetErrorMessage,nullptr,JSMSG_CANT_CONVERT_TO,"null","object");returnnullptr;}returnsuperBase;}JSObject*js::SuperFunOperation(JSContext*cx,HandleObjectcallee){MOZ_ASSERT(callee->as<JSFunction>().isClassConstructor());MOZ_ASSERT(callee->as<JSFunction>().nonLazyScript()->isDerivedClassConstructor());RootedObjectsuperFun(cx);if(!GetPrototype(cx,callee,&superFun))returnnullptr;RootedValuesuperFunVal(cx,UndefinedValue());if(!superFun)superFunVal=NullValue();elseif(!superFun->isConstructor())superFunVal=ObjectValue(*superFun);if(superFunVal.isObjectOrNull()){ReportIsNotFunction(cx,superFunVal,JSDVG_IGNORE_STACK,CONSTRUCT);returnnullptr;}returnsuperFun;}booljs::ThrowInitializedThis(JSContext*cx,AbstractFramePtrframe){JS_ReportErrorNumberASCII(cx,GetErrorMessage,nullptr,JSMSG_REINIT_THIS);returnfalse;}booljs::SetPropertySuper(JSContext*cx,HandleObjectobj,HandleValuereceiver,HandlePropertyNamename,HandleValuerval,boolstrict){RootedIdid(cx,NameToId(name));ObjectOpResultresult;if(!SetProperty(cx,obj,id,rval,receiver,result))returnfalse;returnresult.checkStrictErrorOrWarning(cx,obj,id,strict);}